Ars Militaris Logo

Ars Militaris

Welcome to Ars Militaris.






This Week in Ars Militaris IX

This Week in Ars Militaris VIII

This Week in Ars Militaris VII

This Week in Ars Militaris VI

This Week in Ars Militaris V

This Week in Ars Militaris IV

This Week in Ars Militaris III

This Week in Ars Militaris II

This Week in Ars Militaris I

This Week in Ars Militaris I

This week marks a return to the development of Ars Militaris. This means that development has now restarted and is now undergoing.

This also marks the beginning of our new development lifecycle, which is week-based, and will contribute to bring about weekly updates, both to the game and to our community. One of these new updates is this very newsletter, which will serve to keep you informed about all the recent developments in Ars Militaris.

This newsletter will be published by email to subscribers and will be made available for the public at Ars Militaris' web site (

What is Ars Militaris?

Ars Militaris is an in-development Turn-Based Tactics game set in the Ancient Rome era. It is inspired by Tactics Ogre, which is by many people considered to be the pinnacle of the genre. With Ars Militaris, we intend to provide a Turn-Based Tactics experience like Tactics Ogre, while at the same time providing a modern game experience. We also have planned features that are beyond the scope of the original Tactics Ogre games, which will bring about several new aspects of gameplay to the game.

More will be revealed about Ars Militaris in the upcoming weeks.

Current state of the project

In late 2022/early 2023, work started on a new Ars Militaris prototype, with a new engine. After some failed attempts last summer to develop the back-end engine for Ars Militaris in the R language, the focus switched to using the Bevy Engine and the Rust programming language.

The switch to Bevy brought about significant progress in the project, as it is a proper game engine, and its Entity-Component-System (ECS) architecture is ergonomic and allows one to be productive.

So, right now we're developing version 0.1 of Ars Militaris with Bevy. Ars Militaris 0.1 will be the first release of Ars Militaris. It shall serve both as a PoC (Proof of Concept) as well as allowing us to test our recently established development lifecycle. It should provide a playable version of Ars Militaris, containing a single-player tutorial (codenamed "Ambush") and the capability to play multiplayer battles, with a lobby system. The opponents can either be AI or human opponents.

We're aiming for a release for Ars Militaris 0.1 at the end of the month of July.

Stay tuned for more Ars Militaris news.

This Week in Ars Militaris II

In this week, significant progress has been made, even if doesn't translate into the visual aspect of the game.

Update to Bevy 0.11 and deploying to server

Instead, developments were made regarding the infrastructure of the project, including updating the current Ars Militaris prototype to use the recently-released version 0.11 of Bevy, and deploying our prototype server application to a real server, and connect to it using our game clients.

These developments required a lot of learning and also solving important bugs that arised due to the new interactions between client and server when communicating on a real network. One of the learnings was setting up a easy way to build and deploy the server application. Because this application is to run on a Linux server, and our development environment is a Windows machine, when we tried to cross-compile the server and ran into errors, instead we used WSL2 (Windows Subsystem for Linux 2) to compile the application natively for Linux, and then also used it to deploy it to the server using the `scp` command. With this setup, with just two commands (`cargo build --release` and `scp ...`), we can build a release and deploy it to the server. This setup is very useful as it allows us to be more productive in testing the application.

Our new email:

We now have an email address to which you can communicate to, and from which we will send our newsletter (including This Week in Ars Militaris) to subscribers. You can now see it listed in the **Contact** section of this page.

New test release

With a new Friday comes a new Ars Militaris release. At least that is the goal of our development lifecycle. And this week we have a new release which, as we said before, may not be the most visual appealing, but represents an important step in the project, where a real Ars Militaris client can connect to the Ars Militaris server running on a real server.

This means that this release is "playable", in the sense that you can start the game and enter an Ars Militaris battle. The game even supports multiple players, with two of them actually playing the battle and the rest spectating.

But don't be fooled, there is still very limited interaction and content available. It is more of a test of the viability of the current architecture, and so far the results have been promising.

Also, currently the server only supports one battle at a time, and has to be restarted every time the battle finishes. So, even if you download the game from the button above, you may find that you can't connect to the server as it may not be available. But you can contact us and we can set up a playtest session. We would greatly enjoy that.

Conclusion and next steps

This was a very important week, as it dealt with foundational aspects of the project. With these in place, we can now progress in the direction of adding more gameplay features to the prototype. So by next week we should have more significant developments to show.

We should also note that we were successful in following our development lifecycle, as we managed to put in at least 4 hours of daily work, and have a release on Friday.

Stay tuned for more Ars Militaris news.

This Week in Ars Militaris III

This week has perhaps been one of the most productive weeks in Ars Militaris history. We made significant progress in various aspects of the game.

Integrating `bevy-inspector-egui` and `bevy_console`

The progress that has been made has been made possible by the integration of the `bevy-inspector-egui` and `bevy_console` plugins.

Adding these plugins and connecting them to the existing architecture increased our productivity to new levels. With `bevy-inspector-egui`'s WorldInspector and ResourceInspector, the game data is easily viewable and manipulated right in the game. And with `bevy_console` we now have a fun way of communicating with the Ars Militaris architecture.

The addition of these two plugins also marks the start of the creating of the Ars Militaris Editor, which will be used to create the content for the game, such as the single-player scenarios and campaigns.

"Ambush" single-player scenario

We made slight progress in the creation of our first single-player scenario, codenamed "Ambush". Now, when a player presses the 'M' key at the Main Menu, they will be presented with an Ars Militaris scenario consisting of a map (20x20 grid), and two teams (Carthaginians vs Celts).

Keep in mind that this scenario is not playable yet. But, the player can now interact with it using the tools mentioned above. They can use the WorldInspector to issue new `UnitAction` commands, or also do this using the Ars Militaris console (which is built on top of `bevy_console`).

The currently available `UnitAction`s are the `DoNothing`, `Talk`, and `Move` `UnitAction`s.

Ars Militaris Demo

Work has started on creating the Ars Militaris Demo, which, as inspired by Tactics Ogre, starts playing upon the player being idle for a long time while in the Main Menu. This demo is a short demonstration of an Ars Militaris battle, and it is not interactable. Instead, it is more of a showcase.

To create this demo, some new features were required to be developed. This is good, because these features will also be useful for the other aspects of the game. For example, we are now developing our first animation, the animation for the `Move` `UnitAction`, which, for now, consists of the unit "sliding" to its new location.

Linux release

We now have a Linux build of the game available for download at the top of the web site.

It has not been tested on a proper Linux system, only on WSL2 (Windows Subsystem for Linux) running with graphics support (WSL2g).

We would welcome playtesters for the Linux version.

Stream and YouTube channel

We started the Ars Militaris YouTube channel for all the content related to Ars Militaris and its development.

Right now, this channel serves as the host for our livestream of Ars Militaris development. And soon we will be publishing much more content that we have planned.

Check it out at @ArsMilitarisDev

Contributing back to Bevy Engine

As much time was spent developing Ars Militaris this past few weeks, and the level of knowledge about Bevy Engine and its usage has increased, the opportunity has come to contribute back to Bevy. As it is an open-source project that welcomes contributions, it makes complete sense if one is using it, to support it. And we will soon make our first contributions to Bevy Engine. These will come mainly in the form of documentation contributions, but also a contribution to a PR of a new feature of Bevy.

This feature is the `log_to_file` functionality, and the PR is #5342. We found a solution to the issue of capturing "panics" in a Bevy application. We believe that this functionality is a very important one, and that it would be good if it would be included in Bevy.

We are now using this feature, which required us to use our own patched version of Bevy. Having accomplished this is a result of the aforementioned increase in the understanding of Bevy, and of Rust.

Conclusion and next steps

Because this week has been so productive, we are feeling really good about Ars Militaris right now. We have the fundamental stepping stones in place to build the project upon. This means we are confident that we can release Ars Militaris 0.1.0 at our planned time (in about two weeks).

We also have some surprises in store for you, that will be revealed at next week's issue.

So, stay tuned for more Ars Militaris news.

This Week in Ars Militaris IV

Good Friday everyone. We start this issue with two pieces of information: the first one is that this issue of This Week in Ars Militaris will be the biggest one until now. The second is that we are postponing the release of Ars Militaris 0.1 by one week. We will explain why.

Postponing 0.1 release by one week

In the first issue of This Week in Ars Militaris, we stated that we were aiming for an Ars Militaris 0.1 release at the end of July. We have now decided that our release schedule will follow our weekly development lifecycle, so it makes sense to publish it on a Friday. We also want the latest version of Ars Militaris to be ready in time for when the players finish their workday and decide to play some chill games. With this, we thought that, while the current development has progressed steadily, and we added a lot of features to the prototype, it would be better to postpone the 0.1 release to the 4th of July, so that we could have more time to polish it and, basically, make the current prototype look and behave more like a proper game.

This adjusment will prove very beneficial as it gives more time to Ars Militaris to be presentable, so that in the end the players can enjoy it more. But, this doesn't mean we haven't made progress. You'll find out more about it in the later sections of this issue.

Now, if you're curious to know more about the developers of Ars Militaris, pay attention to the following two pieces.

About Ars Militaris Dev

Ars Militaris Dev ("amdev" for short) is the company/organization developing Ars Militaris. It was founded by its Lead Developer (who you can get to know in the following section) in September 30th 2014 (in the spiritual realm, not as a legal entity). During this whole time its single goal has been to develop Ars Militaris, but we have not been active for some years. We have quite an history already. As it is quite long, we will be starting to publish some History of Ars Militaris articles, in several parts, in the next issues.

For now, it suffices to say that we are based in Lisbon, Portugal, have consisted of two members for the past 4 years, and are currently thrilled and enjoying one of our most productive periods in the project's history.

About the Lead Developer

Assalamu Allaikum. My name is Raoul Abdullah (born Raúl Cardeira), a 30-years-old Portuguese born in France. Ever since my childhood I have had three main interests: 1) playing football (soccer) with my brother and friends and eventually in some football teams; 2) gangsta rap music, which my brother introduced me to when he bought his first Eminem and 50 Cent CDs; 3) computers, mostly playing games.

Perhaps the best way to start this story is with a story in itself. When I was a child we had a PlayStation 1. That was where I first played Tactics Ogre: Let Us Cling Together. I don't even know how I got the game, because I don't remember buying it. I immediately loved this game, and started playing it. Eventually I had reached about Lvl 17 with most of my units (the game has a Lvl limit of 50). But, something very bad happened. My brother, either accidently, or on purpose, either deleted or overwrote my save of the game in the memory card. I think that he can have done that on purpose, because he wasn't that much into this type of game, the only games he played were the ones related with football (like Pro Evolution Soccer and Football Manager), and he also played some wrestling games (he was a fan of Booker T), and he sometimes did things just to annoy me. I was so angry, it was one of the times that I remember being the most angry towards him. Ever since then, I haven't been able to play Tactics Ogre past Lvl 10 or so. I always play my favourite part of the game (which is the beginning), and then stop, for some strange reason. Sadly, my brother passed away 10 years ago from suicide. It has been very hard to deal with that. But, I now view this event of him having deleted the save as a memory of him, and as such I feel his presence, and enjoy it. I really miss you bro! Luckily, I still have two more brothers. Without them, I would feel much more lonely. But I think that soon I will be ready to finally overcome this and go through a complete playthrough of Tactics Ogre, as it is something that I want.

I was a normal, regular gamer, which enjoyed Strategy, Simulation and City-Building games, but then also got into some competitive games like Counter-Strike 1.6, where I was part of a clan for a while, and then League of Legends, where I am a Warwick/Trundle Jungler in Silver elo (my highest has been Gold), and Age of Empires II (multiplayer), where I fight for my position as a top #10000 player, with a sick one-trick strategy with the Portuguese civilization which involves lots of Battering Rams.

But when I first got the idea for Ars Militaris, and decided that I could develop it (even if it was a far too ambitious project), I started to learn programming and learning about game development. The first engine I got to know was Unity, but it took about three years until I finally succeeded in learning to program and create my first prototypes for the game.

Eventually I was finding some success with these prototypes, being able to create more and more features of the game. But I knew that my programming skills were not high, and I was starting to face difficulties such as high memory usage of the prototype due to some bad code. And at some point, when I tried to implement networking into the prototype for the multiplayer aspect, even though I had some initial success, for other, personal reasons, I got side-tracked from the project.

At this time, I was working as a Support Engineer at a software company. This company encouraged learning, and this is when I really started to get more deep into Computer Science. I read interesting articles on HackerNews daily and discovered a lot of concepts, tools, and other things related to computers. This is when I first got to know Rust, and I also discovered the Amethyst Game Engine.

I followed the Amethyst project for some years, but always felt that it was not very beginner-friendly, even if I didn't test if properly myself. So I didn't try to develop Ars Militaris with it, as I didn't even know Rust at that point.

And then I discovered Bevy, from its announcement on the Amethyst forum, and also from the "Elephant in the room" post. I don't know any of the details of what happened between Bevy and Amethyst, as I stopped following the projects for some time after that.

It was last year, when I got motivated to develop Ars Militaris again. By this time I had developed some systems for the game using the R language. I was having some success with that, but the time came to develop a front-end for the game. I initially tried with a simple, no-game-engine, HTML + JavaScript front-end. But while it worked, it was very limited and not good enough. So, I finally decided to try out Bevy. And I was amazed by how easy it was to get started with using the engine. That's due to the ergonomic aspect of Bevy, which is very well developed.

Eventually, around January this year, I moved out of the R backend, and created a new back-end with Bevy. And with these setup (Bevy client <-> Bevy server), for the first time I was able to have the Ars Militaris prototype with a working multiplayer aspect (using the `bevy_quinnet` plugin). This was a major achievement for the project, as it meant that we could move on, as that stepping stone was already in place.

So, for the last 6 months I have been, on and off, developing Ars Militaris fully with Bevy. By now, I have accumulated some experience, and am fairly confident in saying that I now consider myself an intermediate Bevy dev. I am happy with the current state of Ars Militaris, even more having in mind the fact that it was developed by an amateur, self-taught programmer.

So, that's it for an introduction. Regarding my interests other than Ars Militaris, you would think that my football career is over, after the many injuries (both physical and mental) that I've suffered. But I feel that my days in football are not over, and I have some surprises prepared. And regarding gangsta rap, I also have some suprises in store. I also still try to play some chill games of Age of Empires or League of Legends to cooldown from Ars Militaris development.

Contributions to the community

In this week we also bring you the work we have done that resulted in contributions to Bevy Engine or the wider community.

Bevy Timer example

When the time came to develop the first animation for our game, namely, the animation for the `Move` `UnitAction`, which consists of the unit "sliding" from one tile to the next, we had necessity of using Bevy's `Timer`s. It took some learning to understand that the `Timer`s have to be ticked, but once that was learned we started to make good use of them. But, while going through the `` example in Bevy's repository, we came across an inconsistency or even mistake in the documentation for the `print_when_completed` system. It stated that this system would tick the `Timer` component on every entity in the scene. But this was not correct, as this system only ticks the `Timer` on entities with the `PrintOnCompletionTimer` component. So, we created a PR to Bevy with our suggestion of a modification to the documentation of this system. In our proposal the documentation clearly states that this system will only tick the `Timer` on entities with the `PrintOnCompletionTimer` component.

This was our first PR ever, and we're pretty proud of making our first contribution to open-source. With it we learned how to use GitHub for that, which included learning that you can edit the source code of a project right in GitHub. The PR is PR#9290 in case you're interested.

Bevy Cheatbook Windows Window icon page

If you've visited our web site or downloaded the game, you might have noticed that we now have a new icon. This new icon was produced from the main Ars Militaris logo, and it is to be used for the executable icon, as well as the Window and Taskbar icon. In order to configure Bevy to display the new icon, we also followed Bevy Cheatbook's page ( on producing a good looking release for the Windows platform. For us, it was very important to see how far Bevy could go in producing this good looking release, with a nice icon. And we were very happy to find that Bevy can produce a very good looking release of a game. Perhaps even the most beautiful aspect of Bevy is how the release can contain only the executable and the `assets` folder. And doesn't even need an install. So, we're thrilled by this simplicity.

When following the Bevy Cheatbook's page, we noticed that it wasn't updated to be in accordance with Bevy 0.10, namely, with the Windows-as-Entites feature that was introduced in this release. But we were able to adapt the example to the recent version of Bevy. With this, we decided that we could contribute back to this book with our suggestion of an update. But when the time came to do that, we first took a look at the existing PR in the book's GitHub repository, and found out that there was already a PR (PR #212) with this update, and with a better solution that ours. So, this was another learning, that one should always consult the existing Issues and PRs to see if that specific aspect is already being worked on.

Bevy `log_file`

When we started testing the release builds of Ars Militaris, we were soon faced with a difficulty, namely, the fact that if one is running a release build on Windows, if the application crashes, the debug console that is opened when the game launches is close immediately, leaving the user with no option to inspect the logs of the application.

Also, another time when we met the same issue was in deploying our Ars Militaris server application. If one has the program running in the background, we couldn't find a way to view the logs of it. So, we needed the ability to capture the log here again.

Facing this, we decided to explore the options for logging the Bevy output to a file. And exploring Bevy's Issues and Pull Requests, we found out Issue #5233, which describes exactly this aspect of Bevy, and proposes a solution, and then we also found PR#5342, which contains an updated `LogPlugin` for use in Bevy that can save the logs to a file. We also found yet another solution, by the devs of the Digital Extinction game. With this options, we decided to try to use the one proposed in PR#5342.

We were able to integrate this PR into our project, but for that we had to do some nifty `git` usage, in order to understand which was the specific commit of Bevy that that PR was on, and how to then ensure that we could update it correctly. With `git` we were able to check if the files modified by this PR had themselves been modified by any Bevy commit after that date.

There was only one problem remaining, though. If the Bevy application encountered a `panic`, it would still crash and the `panic` wouldn't get captured by the log to file functionality. At this point, some help from ChatGPT turned up to be very valuable: a simple solution for capturing panics, called a "panic hook". With the following line, at the beginning of the `main()` function:


we set a `custom_panic_hook`, that then can be just:

// Logging
fn custom_panic_hook(info: &std::panic::PanicInfo) {
    // Perform any necessary logging or error handling here
    error!("Panic occurred: {:?}", info);

In this way, `panics` are correctly logged to the log file. This is a good solution for now, but we are of the opinion that this functionality should be included in Bevy's `LogPlugin` by default. There's one caveat to this implementation, though. We don't know how the "panic hook" could be included in the `LogPlugin`, as it should be placed at the beginning of the `main()` function. So, we currently don't know how this can be done.

Inspecting the State Resource with ResourceInspector

After some time using `bevy-inspector-egui`'s `ResourceInspector`, we had the idea that if it can inspect any Resource in a Bevy app, it could be used to inspect and manipulate the current state of the States our game. Because these States live in the `State` Resource, we could just use the following line:


And we would have a `ResourceInspector` for that State. Doing this required patching the `` file in the `bevy_ecs` crate, so that the `State` type would be made reflectable. After doing this, the `ResourceInspector` showed up correctly in our game. And it allowed manipulating the current state. There's one caveat to this though. If one manipulates the state using this inspector, the `apply_state_transitions` system of Bevy will not run, so the state transitions, namely, the `OnEnter()`, `OnTransition()`, and `OnExit()` schedules will not run.

At this point, we realized one more thing. If the changing of States is done through the `NextState` Resource, we could also have a `ResourceInspector` for it. And this one would allow us to manipulate the current state and have the state transitions occur. So we did the same as we had done before with the `State` type, but now with the `NextState` type. Unfortunately, we weren't able to have it displaying correctly in the `ResourceInspector`, as it displays the message `Option::Some has unconstructable fields. Consider adding #[reflect(Default)] to - amclient::GameState`. Even though we have added it. We think the problem is that `NextState` contains an `Option` and we don't properly know how to deal with that in `ResourceInspector`.

But, as a workaround, we think it is not difficult to implement a custom Resource, that will contain the same data as the `State` Resource, and have a `ResourceInspector` for it with a button to trigger the running of the `apply_state_transitions` system. But we still haven't got around to try to implement this.

A word for Nu Game Engine

As part of our contributions, we decided to start financially supporting an open-source project. So, we became Sponsors of the Nu Game Engine. We would like to share word about this engine, as we believe it is a really cool project.

As the developer of Nu states, "The Nu Game Engine is the world's first practical functional 2D and 3D cross-platform game engine. Built in F#, it offers a declarative Elm-style programming API, as well as an algebraic ECS programming API for additional scalability. Nu offers a path to a future where game developers are liberated from imperative, OO game programming style. After nearly 10,000 commits, the implementation has matured enough to prove both the efficacy and viability of functional programming techniques in games in terms of performance, programmability, and reliability. Nu currently utilizes SDL2, OpenGL, Aether 2D Physics, and Bullet 3D Physics."

We have been following Nu for some years, and have recently tried it out, including testing some of its example projects. We were impressed by the quality of these projects, especially the OmniBlade game demo. We become interested in Nu due to our interest in Functional Programming, and actually think that we found out about Nu with a Google ("functional game engine") search.

Our decision to become Sponsors is motivated by our ideals in the sustainability of projects in which we believe in. And the fact is that Nu could use some help in this regard. We initially had thought of supporting Bevy, but we saw the fact that Bevy is already receiving substantial support from its current Sponsors. So, we decided that Nu was more in need, and that our Sponsorship would better be directed to them.

So, if you are interested in Functional Programming, or are curious about this engine, you can just check it out (

New Ars Militaris features

New assets for "Ambush" scenario

For our first single-player scenario, which will serve also as a Tutorial, we were in need of some assets, namely, for two units: a Celt Archer, and a Celt Musician. So, we took the steps to produce. Currently, our method of developing the assets for Ars Militaris is top-secret. But it resulted in producing these two needed assets.

We are yet to use these new units in Ars Militaris, but you can already see them, by downloading the game and visiting the `assets` folder.

First animation (Move)

In this week, we developed the first animation for Ars Militaris: the animation for the `Move` `UnitAction` of the units. It consists on the unit "sliding" from one tile to the next tile.

To develop this animation we made use of Bevy's `Timer`s, and also had to face some difficulties with the z-ordering of the units when the movement is occurring.

You can check out this animation by starting the current "Ambush" prototype, opening the Ars Militaris console by pressing the '\' (Backslash) key, and using the `move` console command. For example, try out the following commands in sequence:

move 1 2 1
move 1 3 1
move 1 4 1
move 1 5 1
move 1 6 1
move 1 6 2
move 1 6 3
move 1 6 4
move 1 6 5

We will explain the `move` command. The first parameter (in the sequence above, its value is 1 every time), is the `UnitId`, which represents the unit to move. In this case, we are moving Unit 1 every time. The second parameter is the X coordinate of the destination tile. And the last parameter is the Y coordinate of the destination tile (keep in mind the tile array is 0-based).

With the above sequence, you should see the first unit sliding across the tiles. Note: Please don't try to have an unit move diagonally. If you do, you will probably see some z-ordering bugs, as units are not supposed to move diagonally in Ars Militaris.

Second State: `TurnState`

In one of our days, while we were streaming, a viewer showed up and we talked a bit about Bevy States and how they are so useful. They said they were using two States in their game, one for the main state of the game and another for handling the turn logic of the game.

Inspired by this, we implemented a similar solution for Ars Militaris, to handle the turn logic in single-player battles. So, we now have a `TurnState` responsible for handling this aspect. This way of using Bevy states is very useful as they are orthogonal to each other. So, modifying a state won't change the other (unless you specify it).

With this implementation, a player can now, when in the "Ambush" scenario, press the 'T' key to end the current unit turn. The game will automatically move on to the next unit, and start its turn.

If the unit whose turn it is is controlled by the AI, the game will start an AI turn. And with this we move on to the next section.

First AI

This week also marks the time where the first AI for Ars Militaris was started to be developed. Right now, this AI is really a prototype AI, basically, an only knows how to do one action, which is to make a movement in the -X (negative X) direction (which corresponds to West in the game), and then end its turn.

So, if you try out the "Ambush" scenario, and end all your units' turns by pressing 'T' eight times, you will see the AI playing their units' turns. Once the AI has played all its units turns, it will be time for the human player to play his turns again.

There are many ways to build an AI for a game, and we don't have any experience in that. We think that this simple AI is called a rule-based AI. We will soon be looking into how we can expand this AI. But we are already very proud of this achievement.

Ars Militaris Event #1

Last Friday, we hosted the first Ars Militaris Event of this new era of Ars Militaris. We hosted it at our friend's car shop, TougeWorks.

The Event consisted in the following: we brought our pristine physical prototype (a board game version of Ars Militaris), and hosted a playtest session with our friends. This is because the current prototype of the board game version of Ars Militaris is already playable.

The playtest session went smoothly, even if it took some time to properly explain the rules and have them understand them before starting to play. But once the rules were understood and the battle set up, it didn't take long for the players to play their turns, and the battle finished in about 30-45 minutes of playtime.

It had been a long time since this physical prototype version was played. And the feedback was very positive, and some friends which hadn't yet had the opportunity to play the game, did enjoy it. So, we are planning more Ars Militaris Events. Ideally, we would host one Ars Militaris Event per weekend. But we don't promise it will be possible.

Unfortunately, no pictures were recorded of this event. We could have some nice photos of the "pristine" Ars Militaris prototype, which is very good looking. This is something that we will change. In the following events, we will record some battle logs.

The next Ars Militaris event is planned for tomorrow afternoon, and it will happen at the Conflux store. Again, we will be hosting some playtest sessions with our friends. We'll make sure bring some nice pictures this time.

Conclusion and next steps

The past few weeks have been incredible for Ars Militaris. We have achieved progress in various aspects of Ars Militaris. Perhaps we could make faster progress if we advanced in one single direction at a time, instead of dividing our attention between different aspects of Ars Militaris, but it is important for us that we are building Ars Militaris in accordance to what we have envisioned.

We are hoping for another productive week, which will result in the release of Ars Militaris 0.1. We have a lot of new features listed that we want to develop. But it is important to control the feature creep.

As a reminder, this is what we are planning for Ars Militaris 0.1:

We are dropping the lobby feature for now, as we feel it will require some more work, and we will instead delay it for the Ars Militaris 0.2 release.

So, we hope you have enjoyed this longer issue. Stay tuned for more Ars Militaris news.

This Week in Ars Militaris V


Good Friday everyone. This week’s issue will be mostly focused on Ars Militaris and the actual game aspects. We have already covered other areas of its development, and now the time has come for it to properly be taken into attention.

But, first, we start this issue with a declaration.

Ars Militaris Declaration of Independence

We couldn’t stop noticing that we made a mistake in last week’s issue. We stated that Ars Militaris 0.1 would be released on the 4th of July, but July was already gone and we wanted to have said 4th of August. But, as the 4th of July marks the Independence Day in the U.S., we will now take this opportunity to add another step of our own history.

So we’re announcing the Ars Militaris Declaration of Independence.

We thus hereby declare that Ars Militaris Dev will forever be an independent games studio. This is in continuation of our past history as independent game developers. We went through a long journey already, and had some experiences with the games industry, including with other studios, developers, or even publishers.

With these experiences in mind, and having considered what’s best for Ars Militaris, we have decided that we will remain an independent studio, and will strive to follow the path of other independent games like, for example, EverQuest.

We do realize that this will mean that we will have to handle several more aspects of the game ourselves, but we believe that this decision will utimately be the best for Ars Militaris.

Ars Militaris 0.1 Release

Now that we’re over with the Declaration of Independence, let us talk about another great moment, which is the release of Ars Militaris 0.1. As we had stated before, this version is intented to primarily serve as a Proof-of-Concept for our game. And we’re thrilled to announce that we are satisfied with the current state of it, as we believe that it shows the basic mechanics of the game to prospective players.

So, Ars Militaris 0.1 is currently available for release (at the Downloads section of this website), for Windows and Linux platforms. We will soon have the MacOS version ready as well.

So, what is contained in this release:

  1. Main Menu
  2. Single-player Ambush scenario (battle against AI)
  3. Multiplayer scenario prototype (only available upon request to the devs)

This release is the result of the solid work that has occurred in the past 5 weeks, that has built on top of the work that had been done in the previous 6 months with the start of the development of the Ars Militaris architecture.

Instructions for playing the game

Download the game from the website, extract it and read the file.

Start the game by double-clicking the amclient.exe executable.

You will be presented with the Main Menu. You have four options:

  1. Demo (the Ars Militaris demo, which is a showcase of Ars Militaris consisting of a simulated battle, but which is not available yet)
  2. Ambush (single-player battle against AI)
  3. Multiplayer (multi-player battle prototype only available upon request to the devs)
  4. Quit (to quit the game)

We would wish that you start by checking out our demo, but unfortunately we couldn’t get it ready for this release. Instead, you can start by choosing the Ambush option. You will be presented with the Ambush scenario, where you will control a squad of 8 Carthaginian soldiers (7 Libyan Spearman and 1 Libyan Captain) against 8 Celt Naked Fanatics (6 Spearman and 2 Swordsman).

When the scenario loads, the game will enter the WaitTurn state, which is a central mechanic of Ars Militaris. In this state, every unit’s WaitTurn attribute is decreased by 1, and if a unit’s WaitTurn becomes 0, that unit gets the chance to have its turn. This is the way turns are decided in Ars Militaris.

The WaitTurn state will take some time to execute, but once finished it will be the first unit’s turn, which in this scenario corresponds to your first unit. You will be presented with a Cursor, that you can control with the ‘WASD’ keys. This cursor is very important as it is the main form of interaction with Ars Militaris at the moment.

We should also note that you can move the camera by moving the mouse to the edge of the window, this will allow you to navigate the battle environment.

So, now you’re in a unit’s turn. What can you do? You can do three things: you can issue a Move UnitAction, to move your unit, or you can issue a BasicAttack UnitAction, to make a basic attack against another unit, or you can issue a EndTurn UnitAction. The keys for these commands are the ‘M’ key for the Move UnitAction, the ‘F’ for the BasicAttack UnitAction, and the ‘T’ key for the EndTurn UnitAction. The two first commands follow the same implementation: first you press the desired key, and the possibles tiles that you can move to or attack will show up. Then, move the cursor to the desired target, and press the command key again. The command will be executed if possible. At any time, you can press ‘Escape’ to cancel the showing of the move or attack tiles. To end the current unit’s turn, you simply press the ‘T’ key (while not in the state where you choose the target attack or move tile).

Ars Militaris Basic Combat System

In order to attack an unit, you have to be at range. You can check a unit’s range by pressing ‘F’ and seeing the tiles which it can attack. We will assume that you want to attack an enemy unit. So, make your movement towards an enemy unit.

Now, if you’re at range to attack, and decide to make an attack against another unit, the following will happen: your unit (the “attacking” unit) will make a basic attack against its target. It will do a certain amount of damage, which is visible in the game logs (in the black console window that shows up beside the game when you start it). If the target unit dies, the combat is over. If not, the target unit will automatically make a counter-attack against the initial attacking unit. Once it has done its counter-attack, the combat is over. This counter-attack mechanic is a fundamental feature of Ars Militaris.

What we just explained is valid for the Melee type of combat. For the Ranged combat type, there is only one difference, namely, that units that have a Ranged AttackType won’t make counter-attacks.

Whilst right now the game has an almost completely absent UI regarding the combat and damage statistics, the most visual indicator of combat is the fact that units will change their direction to face their target/attacker. With this, you can verify that the basic attacks are working correctly. Also, the fact that when an unit dies, it will get removed from the battle.

Another rule: once a unit has made both a BasicAttack and Move UnitActions, its turn will automatically be over and the game will move on to the next unit. But this rule isn’t implemented in the code yet, so you are free to make as many moves and basic attacks as you wish with one unit.

So, right now the Ambush scenario consists of this battle. The winning condition is the good-old “Kill’Em All”, in which you have to kill all enemy units to win the battle. If all your units die, you lose. Either on winning or losing, you will be taken back to the Main Menu.

Multiplayer scenario prototype

We were hoping to have our multiplayer scenario ready for this release. For that, we were hoping that we could use the existing architecture we developed for the single-player battles, for the multiplayer ones. But this will require some adaptation of the systems that compose the battle, and we haven’t been able to do it yet.

The current multiplayer scenario prototype only features a grid of 10x10 tiles, and a cursor that can be used to navigate this grid. What is most important is that this prototype already has the ability for an unit to end its turn by pressing the ‘T’ key, and the game will move on to the next unit, just as in the single-player version.

But that’s basically the one single-feature of the multiplayer prototype. More mechanics will come soon.

So, that’s pretty much it for the Ars Militairs 0.1 release. We are happy that it at least provides the ability to play a single-player battle against a simple AI. That is already enough as a PoC. We hope you give it a try, and if you do, that you enjoy it as much as we do.

Other Ars Militaris News

Ars Militaris Discord server

We now have a Discord server, which you are free to join if you want to have a closer point of contact with Ars Militaris. We link it here Discord and also have linked to it in our new “Social” section at the bottom of the website.

Inclusion in This Week in Rust

It is with great pride that we inform that issue #4 of This Week in Ars Militaris was accepted to be included in This Week in Rust. This Week in Rust is a weekly newsletter containing updates from all-around the Rust community, and it is an honor to be included in such a well-reputed publication.

Scaling Ars Militaris Development

While it has been very positive that we have managed to put in daily work towards Ars Militaris, and that it has resulted in the solid development that has occurred, we realize that Ars Militaris development is currently hindered by the fact that we have only a single dev working on the game.

Thus, we have took some steps towards changing this, with the goal of increasing our output in terms of the development and management of the game and all its aspects.

So, we have started to look for more Co-Founders to join Ars Militaris Dev, which will contribute with their expertise and skills towards the development and management of Ars Militaris.

We have already found two more Co-Founders, which is great, and are actively looking for more still, as we realize Ars Militaris is an ambitious project and it would be good if it has the necessary resources to grow.

And this leads to our next announcement…

Open-sourcing Ars Militaris

It is with great joy and excitement that we announce that Ars Militaris has now been open-sourced. This means you are free to explore the project’s code, on its GitHub repository.

We will explain a bit what this means for Ars Militaris, and how the open-source model fits our business model.

Ars Militaris will be a free-to-play game. This means you will be able to play the game without spending a single cent, if that’s what you want. This also means we will freely distribute the client for the game, so that you can access your Ars Militaris account, which is going to be the central point of interaction of the players with the game.

We open-source our game in an effort to make it more “free” software (“free” as in “free speech” and not in “free beer”, but we will also include some free beers in the offer). So, you will be able to inspect the game code for any analysis you want to make, be it for learning purposes, security audit, or other reasons.

There’s one caveat to our open-sourcing the game, though. The right to use the code will be granted on a use-case basis. This means that if you want to use the code for any endeavour which is not listed on the project’s, you will have to ask us for permission, and we may refuse it. We plan to be very generous, though, and we are only reserving this refusal option for cases where we feel Ars Militaris could be hurt.

So, please go check out the project at our GitHub: amclient and amserver. We are still configuring the repository, but soon we will be starting to accept contributions.

Conclusion and next steps

This has been a action packed week. Unfortunately, our work management and productivity were not the highest in this week, which meant that we couldn’t achieve some of the goals we had set for Ars Militaris 0.1, such as the Demo or an improved AI, or a gameplay video.

But, we still could deliver a working PoC for Ars Militaris, and that is enough to make us feel good.

Now, with the open-sourcing of Ars Militaris and our search for more Co-Founders, we hope that we can increase the available resources for Ars Militaris, to ensure that its development continues progressing steadily.

With this, we can announce that we will now start working on Ars Militaris 0.2, which we plan to release in about a month. We will be announcing its features in the following weeks.

Overall, we continue thrilled and enthusiastic about the future of Ars Militaris..

We hope you enjoyed this issue. Stay tuned for more Ars Militaris news!

This Week in Ars Militaris VI


Good Friday everyone. In this week’s issue, we bring you some updates regarding Ars Militaris and its development. This week was focused on aspects of Ars Militaris other than its digital version. Namely, we started working on a new prototype for the board game version of Ars Militaris. You’ll get to know this work, and other aspects, in the following sections.

Moving Ars Militaris Dev to a new location

Because we’re in August, which is the time for vacations, Lead Developer “cwolf” is now in vacation at his family country house. But, as right now we’re in the most productive period of Ars Militaris’ history, I wouldn’t make sense to stop working right now. So, we brought our development environment with us to this house. And this will bring about yet another new era in Ars Militaris development, because this house allows for some things that were not possible before. Namely, this house has a workshop, where we can build more Ars Militaris boards for the board game version of Ars Militaris. We also are equipped with a new (old) desk, a desk which has served Ars Militaris well in its past, and which we are happy to be together with again.

Now, it takes some time to adjust to a new development environment, namely, a new room, a new desk, new daily routines, etc, so, Ars Militaris (digital) development has somewhat been put on hold for this week. Instead, we’re focusing on organizing other aspects of Ars Militaris. Also, “cwolf” was in need of some kind of break from the intensive development period of the past month. Specifically, because last week’s work wasn’t very organized, “cwolf” suffered a bit from stress due to wanting to have the Ars Militaris 0.1 release ready by Friday. So, now, some chilling is in order.

Ars Militaris Event #2

Two weeks ago, on Saturday, we hosted the Ars Militaris Event #2, at the Conflux store. We took the Ars Militaris pristine board game version to there, and had some friends playtest the board game version of Ars Militaris.

The playtesting session went very well, we played two battles of Ars Militaris. Both battles featured a Roman squad defending their encampment from some Celt Naked Fanatics. In both battles, the Romans won, which was the result of the rules that we established for this specific scenario, in which, if the Roman player could survive for 4 complete game turns, he would win the game. And this is what happened, but we think that perhaps the scenario was somewhat unbalanced. Still, this is exactly why we need to make playtests, to discover these aspects and ensure they are balanced.

After the event was over and our friends had left, it was time for Lead Developer “cwolf” to talk with the owner of the Conflux store about some business aspects of Ars Militaris. Specifically, we tried to get some information regarding the price that we are thinking of for the Ars Militaris board game version. Also, the owner of store, being a veteran board/miniature game player, had some suggestions for some mechanics of Ars Militaris. We accepted these suggestions, but ultimately decided that we won’t change the mechanics of Ars Militaris, as most of them are already set in stone, and it would not be truthful to Ars Militaris to change these mechanics, as we believe they are already pretty good.

So, in this event, we asked our friend @zoomzag to take some photos, and so we bring you here some pictures of the pristine Ars Militaris board game version, and of the battle itself.

Here they come:

Roman Hastati and Princeps
The Roman Captain
Celt Naked Swordsman flanking the Romans
An overview of the main battle location
A Roman Veles (singular for Velites)
Ars Militaris battle showing the cards
Celt Naked Fanatic Druid that has fallen in battle
Another view at the battle
Another view at the battle
The pristine Ars Militaris board

We are very happy about the current state of the board game version of Ars Militaris. Because the playtesting sessions have been going so well, we have reached the conclusion that this board game version is almost ready to be packaged into a final product so that we can sell it.

So, work has started on a new Ars Militaris board, that will be the first Ars Militaris board that we sell. Because the production of an Ars Militaris board game version is somewhat complex and involves different steps and pipelines, we are thinking that we can have this board game version ready in about two months.

Ars Militaris features

We bring you some highlights regarding the development of some features for Ars Militaris.


Last week we put in the necessary work to develop the Ars Militaris cursor, which is a fundamental feature of Ars Militaris. This cursor is the main way the player interacts with an Ars Militaris battle. With the cursor, the player can position it on an unit, to obtain information regarding that unit, or the player can position it on a tile, to obtain information regarding that tile.

Currently, the cursor is only available to be controlled with the ‘WASD’ keys. But we will also implement functionality so that it can be controlled with the mouse as well, and also with touch input once we develop a mobile version of Ars Militaris.

Unit Move Range indicator

In order to have the units move, it was necessary to develop the feature where, when a player is controlling an unit, and specifies the Move UnitAction (by pressing ‘M’), he receives information on the tiles that the current unit can move to. This is the classic “diamond” grid of tiles that is common in square-grid tile-based games.

This feature was implemented with a recursive find_possible_movements function, that gets the available neighbors of the tile the unit is on, and recursively searches for the next neighbor and checks if that tile is available for the unit to move. If it is, the function adds that tile to a Vec, and when it has finished calculating all the possible movements, it returns the Vec with the available tiles’ location.

Here’s the full code for this function:

// Prototype
fn find_possible_movements(map: Vec<Vec<(usize, TileType, Vec<Entity>, Vec<Entity>)>>, start: Pos, mut movement_range: isize) -> Vec<Pos> {
    let mut possible_tiles_vec = Vec::new();
    movement_range -= 1;
    let mut visited_tiles = HashSet::new();
    if movement_range >= 0 {
        // Get neighbors.
        let neighbors = get_valid_neighbors(map.clone(), start);
        for neighbor in &neighbors {
            if visited_tiles.insert(neighbor.0) {
                let mut recursive_possible_tiles = find_possible_movements(map.clone(), neighbor.0, movement_range);
                for possible_tile in recursive_possible_tiles {
                    if !possible_tiles_vec.contains(&possible_tile) {


We already had experience with using recursion for this, as we had already developed this feature for the Ars Militaris Unity prototype that was put on indefinite hold since 2019.

A* Pathfinding

The next thing in order to have the units moving, after getting the available tiles, was to actually have the unit calculate a path towards the destination tile. We decided to use the A* pathfinding algorithm for this, as, again, we already had experience with using this algorithm for the Ars Militaris Unity prototype.

In fact, developing the A* pathfinding for the Ars Militaris Unity prototype was actually one of Lead Developer “cwolf” biggest achievements in programming during that time. Because it was implemented as a custom solution following an article that explained the A* algorithm and provided some pseudo-logic for it. With that, it wasn’t very difficult to implement the algorithm.

But now, 4 years later, the development conditions are completely different. So, we asked ChatGPT for help regarding the A* pathfinding, and it suggested the pathfinding Rust crate that contains a astar method that calculates the A* path. With this, it was very easy to implement A* pathfinding for Ars Militaris.

In truth, sometimes ChatGPT takes some of the joy out of programming, because it is a little bit like cheating. So, I can say I had more fun implementing the A* pathfinding myself, than with the ChatGPT solution. But the priorities are different now, we’re trying to build a real game, and it is actually good that we can cut some corners with help from ChatGPT.

Complete movement system

With the ‘Unit Move Range indicator’ and ‘A* pathfinding’ features implemented, the Ars Militaris movement system is almost complete. Of course, there are some things missing from it yet, like for example, the fact that the movement system is not taking “tile height” into account for calculating the available moves. But this is a small detail that is easy to implement.

Most pressing, though, is the issue where, when a unit is moving, the z_order_system is not working correctly, and bugs appear in the z-ordering when moving a unit. Because this bug is making the game less pleasant to play, as it is basically a serious visual glitch.

Still, we are not worried about this bug. We believe in the principle that, as long as a bug is identified and documented, it is not a big problem because at any time resources can be directed to fix it.

Nginx log web site analytics

Since we set up our website, about 1-2 months ago, we didn’t know of any easy way to have web site analytics so that we could see how many visitors were accessing our website. This was not a huge deal in the early days of the web site, which were more of a test, but, once we started posting our dev log on Bevy’s Discord, and also This Week in Rust, we became curious about how many visitors we were actually getting.

We just wanted a simple solution, but one that we could control, maybe by self-hosting it. We kind of knew about Google Analytics but we didn’t go for that. So, the first tool we found was Plausible, and we managed to install it in our server. But, when we started it, we couldn’t get it to work, as our website is using HTTPS, and even though we followed the steps in Plausible’s documentation for setting it up with HTTPS, we couldn’t get it to work.

At this point, we were really wanting the web site analytics, so we decided to do a Google search for “nginx log analytics” (we use nginx as our web server), because we thought that there could be a simpler way of having web site analytics without installing another app. And it seemed to us that this information could be contained in the nginx logs. This search brought us to NginxLogAnalytics, a .NET core console application for analyzing nginx logs. We were thrilled by this find, as this program was really simple and perfectly fitted our use case.

We did the necessary steps to set up NginxLogAnalytics, which included changing the log_format directive in the nginx configuration file to a custom format that NginxLogAnalytics would parse. After this, we were able to run NginxLogAnalytics, but we discovered a problem with this application. Because we had to change to log_format, NginxLogAnalytics will not read the logs from before the change. This meant that some part of the logs were not accessible to NginxLogAnalytics, and thus we couldn’t analyze our entire web site history with it.

We also ran into some erros while using NginxLogAnalytics. Facing these, we concluded that we would need another option. So, we decided to go and check the nginx logs directly ourselves. And that was a great decision, because, just by using tail -f /var/log/nginx/access.log, we could already get a lot of information on who’s visiting the website. So, this was good progress. But this way is a bit raw, and so we continued to search for more tools. At this point, we remembered that Rust is so popular these days, that it seems that there already exists a tool for every single job written in Rust. So, we searched for “nginx log analytics rust”, and discovered the rhit tool, which does exactly this job. Setting up this tool was just a question of downloading the binary and executing it, as this tool reads the nginx logs in their default format.

With rhit, we discovered that most of the accesses to our website were carried out by bots and not humans. At least that’s what we think, because we see many attempts to access pages or locations that don’t exist in our website. Possibly, this is some malicious activity, that is present in the Internet and which is something that every owner/manager of a website has to deal with. Luckily, we confirmed that our server is responding to these requestes with 400 and 404 HTTP responses, which we understand to mean that the server is correctly responding to these accesses by not giving them any information. This gives us some relief that our web site is secure, even though we don’t know much about Internet security and there can still be other attack vectors available.

But, for now, we were happy to get the information that rhit provides. We could see that we had many more visitors than we expected, which is good. Also, we had to opportunity to witness something that left us thrilled. We were averaging about 350 visits per day (most of them bots). Then, went our newsletter got published in This Week in Rust, we were very curious to see if this number would increase, and by how much. So, the day after, we went to check the statistics with rhit, and to our surprise, we had almost 2.5k visits! And most of them from real persons, because we could see that the number of 400 and 404 responses had decreased, and most of this visits were to our main web page (the / (root) location of the website). The day after, we got another 2.5k visits again. And then in the following days we have been having around 800 daily visits. Also, we can get statistics on how many people have downloaded the current release of Ars Militaris, both for the Windows and Linux versions. And it was very fun to see that the number of downloads of the Linux version increased to the point of surpassing the downloads of the Windows version, which was initially higher because it includes our own downloads of Ars Militaris to test it. So, this means that there are a lot of Rust users that use Linux, so it is important for us that Ars Militaris is playable on this platform.

Needless to say we were humbled by having so many visitors, and we are deeply thankful for This Week in Rust for having provided us with this opportunity to reach more people.

Improved security for our server

Perhaps the aspect of Ars Militaris that we have less knowledge about is computer and network security. So, when we put this website online in a server, we started to become worried that someone might be able to break into the server by brute-forcing the “root” account password with ssh or other tools. Because the reality is that, anybody in the world could just do a ssh, and be presented with a prompt to insert the password. This was the only think stopping people from breaking into the server. But we knew that passwords are not the most secure method of authentication.

So, we did the work necessary to set up ssh keys for the devices that we want to able to access the server. This was actually very easy to do once we understood that we can create a key with ssh-keygen, and then it is just a matter of having the ssh public key in the server’s ~/.ssh/authorized_keys file. We learned this by following the tutorial at (

So, we set up a ssh key for our main computer running Windows, then another one for our WSL2 Ubuntu system (for this one, it was necessary to create a new user in the Ubuntu system, because, if the username in WSL2 is the same as the Windows username, the sshd daemon in the server assume that the connection is coming from the Windows user and not from the WSL2 user), and we also installed the JuiceSSH tool on our Android phone and configured ssh keys for it. After we had set up these keys, we disabled password authentication in the sshd daemon, by editing its config file at /etc/ssh/sshd_config, and setting the PasswordAuthentication directive to no. So, now, no one can brute-force our passwords anymore, and we get some nice options to connect to the server. As an highlight, we even accessed our server when we were at the beach chilling with JuiceSSH. This is very cool.

We’re now with a feeling of relief because we feel that our server is now more secure than before, even if there can still exist more attack vectors that we don’t know of. As we said, this is the aspect of Ars Militaris which we know less about, so, it is important to get up to speed with the main security features necessary for Ars Militaris. We are welcoming help in this issue, as we really would like for someone to do a security audit of our project. This would really help us feeling even more at ease. This is something we will try to achieve with our “Scaling Ars Militaris Development” program, that we’re going to introduce soon.

Down the cross-compiling for MacOS rabbit hole

Motivated by Bevy Cheatbook’s page on the MacOS platform (, where it is described how one can produce a “proper nice Mac app”, as the author states, we decided to try and produce a release build for this platform. Specifically, we got hooked by the fact we would produce two executables, one for each MacOS architecture (x86_64-apple-darwin and aarch64-apple-darwin in Rust), and combine them into one using the lipo tool. We love command line tools, and it seemed amazing that it would be so simple to accomplish this. We also wanted to produce an icon for the app following the process described in the page.

We ingeniously thought that cross-compiling was a straightforward task, but that turned out to not be the reality. And this was the start of quite a journey, that included a lot of learning. We will describe this journey here.

Since our main motivation at this time was actually to use the lipo tool, the first thing necessary was to obtain this tool. Initially, we thought it was only available for MacOS, but we found a port of it for Linux at ( So, this meant that we could use our WSL2 system to build this tool and use it. So, we built cctools-port. Initially we encountered some erros in the build process, but once we ran the ./configure script without arguments, we were able to build cctools-port successfully. After that we thought that this port didn’t contain lipo as we couldn’t find it, but then we found it in the misc directory.

After this, we tried compiling a release for MacOS, but faced an error, related to the crate objc_exception. We searched online for a bit, and found an issue reported with the same error ( And we found a fork which contains a branch named fix-cross-compile, that changes the file that is giving the error (PR #8). Perhaps using this fork could solve the problem, we thought. But we didn’t have any idea of how we would set up Bevy to use that fork of objc_exception, as we were not that advanced a Rust programmer.

But we decided to proceed and try to do this patch. And this resulted in one of the programming adventures that we are most proud of.

So, we endeavoured in understanding the available tools for studying the dependency graph of a Rust application. Because we needed to see which crates depend on objc_exception, and which crates those in turn depend on, and so on. Because, as this is a change at the base of Bevy, it will require that a lot of crates be patched. Our study started with the cargo tree command, which is available by default with a Rust installation. But this command wasn’t enough for us as it wasn’t finding the objc_exception crate. We tested a few more solutions with help from ChatGPT but to no success. Then, we found out about two (or three!) related projects that allow building a dependency graph. They allowed the production of a visual graph with the dot command from the graphviz tool. The graph built with the cargo-deps cargo tool was corrupted. So I used the recommended cargo-depgraph cargo tool, which was successful in creating the .PNG file with the visual graph. But the graph was just huge, and very hard to understand anything, or find the crates we were looking for.

Here is the dependency graph so you can check for yourself (you can Right-Click + Save Image As to inspect the graph in your own computer):

amclient dependency graph

So, instead of piping the output of cargo depgraph to dot, we just saved it to a file, and saw that it is easily readable and workable, as it is a graph specified in the dot format/language. With this, we could easily search for the crate name, and also for the dependent crates.

Here is how the file looks like in the dot format:

digraph {
    0 [ label = "amclient" shape = box]
    1 [ label = "bevy" ]
    2 [ label = "bevy_quinnet" ]
    3 [ label = "csv" ]
    4 [ label = "embed-resource" color = green3]
    5 [ label = "image" ]
    6 [ label = "serde" color = darkgreen]
    7 [ label = "winit" ]
    8 [ label = "bevy_internal" ]
    9 [ label = "base64 0.13.1" ]
    10 [ label = "bincode" ]
    11 [ label = "bytes" ]
    12 [ label = "futures" ]
    13 [ label = "futures-util" ]
    14 [ label = "quinn" ]
    15 [ label = "quinn-proto" ]

Above this you can see the labels, and below this you can see the graph connections with the from and to label.

    0 -> 1 [ ]
    0 -> 2 [ ]
    0 -> 3 [ ]
    0 -> 4 [ color = green3]
    0 -> 5 [ ]
    0 -> 6 [ ]
    0 -> 7 [ ]
    1 -> 8 [ ]
    2 -> 9 [ ]
    2 -> 1 [ ]

We started manually building the reverse dependency graph for the objc_exception crate. And it was not that hard. Along the way, we had to install Notepad++, because we needed a very important feature, namely, the ability to “count” the number of “finds” with Ctrl+F. And Notepad++ does this very well, and even has the option “Find All in Current Document”, which opens a panel with the search results. This was really useful for the task at hand, which involved counting the number of “connections” in the graph related to that crate and its dependants.

After some time, we realize that the number of crates that would be needed to patch was higher than 10, and got a bit demoralized. But just after that, we checked the cargo tree documentation, and found that there is an option, –invert, that does exactly what I was doing manually. But this manual work was a great learning experience, for the first time we used graphviz to create a graph which would help understand a software. This had been one of the goals of “cwolf” for quite some time, to have better ways in which to understand software. Also, the cargo tree output brought some promising results. It seemed that the total of crates that would need to be patched was 17. That’s not a huge number, and we felt like we could tackle it. We were really curious to see if we could get the bug fixed, as that would be simply amazing.

So, we decided to tackle this issue. We cloned the repository with the PR fix (PR #8) for objc_exception, and built it for Apple architecture, namely, the x86_64-apple-darwin architecture. And it built successfully. Then, we moved on to the following crate in the dependency graph, namely, the objc crate. We updated its Cargo.toml, and built it successfully. Then the same with metal-rs. This was giving us confidence that the bug fix was working.

Then with the next crate, wgpu, the objc_exception error happened again. And it was the same error, with the include objc.h line. At this point, we realized we had taken a step too further, as we should be dealing first with the wgpu-hal crate. And we updated that crate, and it built successfully. But we found a thing that puzzled us, in this crate’s Cargo.toml they are specifying a specific git branch, not a release version of metal-rs. So we kind of didn’t know what to do here, because we didn’t know if the version of metal-rs we had was already at the same commit as that one. But we could check that with git rev-parse . This is a very useful command that was just perfect for this situation. And with that command we could see that our version of metal-rs contained the commit we were looking for.

Then we updated wgpu-core, and then wgpu itself. But this wasn’t successful. Now it was the crate nv-flip-sys that is giving problems. At this point, we were kind of tired from this adventure, and decided to quit pursuing this fix, deeming it as still one to complex for us. But the joy we felt when going down this rabbit hole can’t easily be described. It resulted in a huge gain in understanding of a Rust project and its dependencies.

After this, we made a post on Bevy’s Discord #mac platform channel, asking if anyone could help me with this issue of cross-compiling. And we were suggested that instead of cross-compiling for MacOS, we could have a GitHub Action to build the project for MacOS, as GitHub offers the option of MacOS Virtual Machines for their Actions. The problem was that our project was not on GitHub at this point, but now it is. So, we are working on developing this “Build for MacOS” GitHub Action, that will produce a MacOS release of Ars Militaris. We are counting on having these MacOS version ready soon enough, as it is very important for us. Due to fact that we’re using bevy_quinnet as our networking crate, and, unfortunately, QUIC is not supported on browsers, we can’t build our game for WebAssembly, to have the players play it directly in their browser. So, we really need a MacOS version, otherwise, players with a Mac won’t be able to play the game at all, and this is something that we don’t want. We want Ars Militaris to be available for every player and platform.

An (almost) seriously costly mistake (with ChatGPT and sed)

We now bring an almost destructive story that happened to us.

So, for the past year, we have been writing a development diary, which we call the Ars Militaris Dev Log. We started writing this diary last summer, when we were developing one of the Ars Militaris prototypes with the R programming language. Also, we should say that the habit of writing a diary with the logs of our work, is a habit that we developed when we worked at SIAG, a Portuguese ERP SaaS company. While working there, we were required to write a log for every task that we accomplished. While this habit was a bit strict, it results in having an abundance of information about the development of a certain feature or bug fix.

Anyways, today, this diary has about 850 entries. And, we are planning to turn it into a product that we can offer. So, the first task at hand was to convert the dev log, which is written in a single .txt file (which is actually written mostly as Markdown), to HTML or PDF or another format that is better suited for reading.

We started by using the pandoc tool to convert the diary.txt file to HTML. But, to our surprise, by default pandoc (or Markdown), doesn’t treat line breaks as actual paragraph separators. It needs either for the paragraphs to be separated by an empty line, or, instead, to just add " " (two spaces) at the end of each entry, so that it could be recognized as a paragraph. We decided that it was easier to just add the two spaces at the end of each entry.

At this point, we made the decision to ask ChatGPT for a simple Unix command to add the two spaces to each line in our diary.txt file. It suggested that we used the sed tool, which was a tool we were curious about for a long time. The command it suggested was:

sed 's/$/  /' input_file.txt > output_file.txt

Now, if we had used this command as is, it would have worked correctly. But, smart as we think we are, we decided to modify the command to overwrite the original diary.txt, so, the command we actually used was this:

sed 's/$/  /' diary.txt > diary.txt

We did this with absolute confidence that it will work, and, unfortunately, didn’t remember to create a backup of the diary.txt file. Now, if you are experienced in using sed, you may have noticed that the command we used would not do as we intended. What we can tell you is that, after we ran the command, and generated the HTML version of the diary (with pandoc), we were surprised to just see a completely empty HTML page. Where had the diary gone? So we went to check our diary.txt file, and were absolutely dismayed to see it completely empty.

At this point, we entered a panic mode. Could we really have lost 850, high-quality diary entries? A whole year of writing? Because of a stupid ChatGPT attempt? When we could just have used our favorite text editor, Notepad2, to simply append the two spaces at the end of each entry in a much easier and less dramatic-error-prone way.

Luckily, a divine intervention occurred. The miracle was that, we still had a browser tab open with the previous version of the HTML version of the diary, where the entries were not separated. So, with this, we could copy the entire diary from the browser to a new diary.txt file. Unfortunately, this still resulted in some diary entries lost, but only about 10 or 15 entries were lost.

The relief we felt by having recovered our diary can’t be properly explained. And this was a very big lesson learned. And it is not ChatGPT that is at fault here, it was ourselves. ChatGPT had suggested that if we wanted to modify the original file in place, we could use the -i option of sed. But we didn’t read that and blindly made the mistake.

Other news

Ars Militaris Radio

When we started streaming Ars Militaris development, we were immediately faced with a practical problem. Because we like to listen to music while we’re developing, we were playing some songs from our Gangsta Rap collection, only to immediately get a copyright strike notice from YouTube. This left us pretty sad because music is an important part of our life, and we couldn’t believe that there wasn’t an easy way for having viewers listen to our music. Well, we could (and still can) just create a YouTube playlist with the songs and point the viewers to it, but, because our music collection is stored as old-school .mp3 files in disk, and it has over 750 songs, it would require some work to create a proper YouTube playlist. Also, we should say that we dislike Spotify or other music listening apps, because we find that having our collection is much, much better.

So, we decided to circumvent this issue, by creating our own Radio Station, which we call Ars Militaris Radio. We already had some experience with setting up an online radio, because in late 2019, we also had a server to test some things, as we did set up a radio, using Icecast2 and ezstream.

So, we followed this path again, and set up the Ars Militaris Radio with these two tools. We faced some challenges in setting this up, namely, some strange errors with ezstream, which left us a little bit baffled, but, last weekend, we finally managed to successfully set up the radio.

At this point, we should also say that we considered other solutions, such as having a Discord bot that would play the music, but we were disappointed to find that there is no Discord bot that can play music from disk. Regarding the radio set up, we also tried other solutions, which included setting up nginx to stream RTMP, following the tutorial at ((, and using VLC to both stream to the nginx server, and to the Icecast2 server. None of these solutions was perfect, though.

In the end, we were happy to have our solution working, with Icecast2 and ezstream streaming from our server. So, now the Ars Militaris Radio is live, 24/7. It currently consists of three radio channels:

  1. choppin_blades

This was the channel we initially used for testing. It consists in a stream of only one song, on eternal repeat. The song is “Choppin’ Blades”, by UGK. This is a song that we discovered a few weeks ago, and that has become our favorite rap song at the moment. We leave this channel online, even after the tests were successful, as a way to to honor this song.

  1. gangsta

This channel contains “cwolf”’s Gangsta Rap playlist. It consists in a collection of around 650 songs, playing in shuffle mode, and nearly all of them are G-Funk songs from the 90s.

If you like Gangsta Rap, and have some suggestions for songs for us to play, just reach to us on our Discord, as we would enjoy the opportunity to expand our collection with some sick tracks. It has been a long time since our collection has grown.

  1. tactics_ogre

This channel contains the Tactics Ogre: Let Us Cling Together OST. If you are knowledgeable about Ars Militaris, you should by now already know that Ars Militaris is heavily based on Tactics Ogre: Let Us Cling Together. And, this OST is by far our favorite OST of any game. Unfortunately, the owners of the Tactics Ogre IP (now Square Enix) have made what in our opinion is a Crime Against Humanity, which is to, as they have release Tactics Ogre: Reborn (a remake of Tactics Ogre: LUCT), they have removed from YouTube some of the videos with the old OST.

Personally, I don’t understand how they can do this, leaving the people who love this OST with no option to listen to it anymore. Just imagine if I didn’t have the OST files on disk, and I would never get the chance to listen to this OST again. Luckily, I had already taken the steps to obtain the OST.

So, now, we’re giving the opportunity for listeners to listen to it. We think we are actually doing a service to humanity, but we are aware that the content we are publishing with our Radio is not exactly “legal”. But, our intention is for Ars Militaris Radio to be an underground radio. So, please don’t tell the cops.

By the way, we still have capacity in our Icecast2 server to support some more channels. We have some ideas for more content for the Radio, but, if you, by chance, want to have a channel in our radio, feel free to contact us and we will work together towards this.

First Age of Empires video

Besides belonging to the Bevy community, Lead Developer “cwolf” is also a member of the Age of Empires II community. And, when we want to chill from Ars Militaris development, we play some Age of Empires II: Definitive Edition online multiplayer games. After 10 years playing this game on and off, we’ve actually become quite accomplished at it, being currently positioned around the top #10000 players (which corresponds to about 20% of the AoE online multiplayer players).

We always play with the same strategy (we’re an one-trick), with the Portuguese Civilization, that consists in going for a Fast Castle Age, and then spamming Knights and Battering Rams and make a 1-TC Castle Age all-in towards destroying the enemy completely.

So, we developed a video where we explain this strategy. You can check it out at ( It is our first AoE video, so bear with us a little bit on the production value.

It was a lot of fun to produce this video, and we also have more recordings of our games, that we will prepare to create a fun montage. We also have another surprise regarding AoE and Gangsta Rap, but it is not the time to share it yet.

Conclusion and next steps

This week was more of a chill week. Because Lead Developer “cwolf” needed some time to rest from development, and the opportunity to go on vacation to the country house came by, it has resulted in a week where we focused on other aspects of Ars Militaris other than the digital game.

So, not a single line of code was written this week, but this isn’t a problem. By now we have adapted to the new environment and can start being productive towards the digital version of Ars Militaris as well as the other aspects of the game.

Regarding the next steps in the project, we have the following plan right now:

Overall, we couldn’t be happier with the current state of the project. Things are going really well, and we don’t see any obstacle in our path right now. All the things that we want to develop have a clear plan that will bring them into existence.

So, we hope you enjoyed this week’s issue, and stay tuned for more Ars Militaris news.

This Week in Ars Militaris VII

Friday, 2023/08/18

Good Friday everyone, and welcome to another issue of This Week in Ars Militaris. This week has seen some progress in the development of Ars Militaris, namely, in the multiplayer aspect of the game. This multiplayer aspect was suffering a bit from long-standing inactivity towards it, as we were focusing first on having the single-player mechanics set in place.

But, this week, the time has come to focus on it, and we can say that some nice developments have been made. You can check them out in the section “New Multiplayer Scenario”.

So, let’s get headlong into this week’s issue.

Ars Militaris Engine

After we open-sourced Ars Militaris and published our two repositories to GitHub (amclient and amserver), we soon noticed something: because we’re using a fork of Bevy, with some patches applied to it, if a contributor wanted to clone the repositories and build them, they would be unsuccessful in this, as they didn’t have the necessary patched Bevy. So, we took to fixing this issue.

This involved publishing our patched Bevy Engine to GitHub, so that contributors would be able to clone it, and build the Ars Militaris projects correctly.

But, this step involved some studying, as we soon found that there were some different ways in which we could approach this.

The first idea that we had was to have the entire Ars Militaris project under a common cargo “workspace”. We took this idea from the Digital Extinction game project, where they are using cargo “workspaces” in their repository. But, we immediately were faced with an obstacle, that is, the fact that cargo doesn’t support “nested” workspaces. And, because Bevy and some of the other crates we’re using are set up as workspaces, we immediately turned away from this solution (later, we were suggested that we could simply “remove” the “workspace” set up from Bevy and the other crates, and just have them as normal crates, but by this time we had already opted for another solution).

The second solution we studied was using git “submodules”, because, we wanted to keep the commit history of the crates we’re using. This involved some set up with git, but, when we were done and pushed the repository to GitHub, we were surprised to see that it didn’t contain the code for the crates that were set up as submodules, instead, it contained just a “link” to these crates with a specific commit hash. We were a bit disappointed by this, because, the first thing we really needed was the actual code of the crates, so the contributors can use it.

The third and final solution, was to simply create a directory, amengine (for Ars Militaris Engine, the name we choose for our patched Bevy (we know it is a rather presumptuous name, as it is really just Bevy with some patches, but we like the name)), with Bevy and the other patched crates, and just upload this directory to the amengine repository on GitHub. This solution allows us to distribute the Ars Militaris Engine code, but, unfortunately, we also lose the commit history of the individual crates, as, in order to have a repository on GitHub, that repository can only contain one git repository (at least from our experience).

Along the way, we also learned that distributing our project’s dependencies in this way, is sometimes called “vendoring” dependencies, so, it comforts us a little bit that this is something that is not unusual in the software industry. We also took notice that we’re probably going to have a hard time when we want to update our dependencies, for example, for the next release of Bevy. As we don’t have the commit history anymore, it will require some skillful git usage to patch these crates again. But, we’ll worry about that when the time comes.

For now, we’re already happy that contributors can clone the amengine repository, have it in the same directory as the other repositories, and they should be able to build Ars Militaris themselves.

MacOS Release

After the “Down the cross-compiling for MacOS rabbit hole” adventure that we described in last week’s issue, and which ultimately was unsucessful in producing a MacOS release of Ars Militaris, we turned to other options. Specifically, one friendly Bevy dev had suggested, in our post in Bevy’s Discord #mac channel, that we could use a GitHub Action to create the MacOS build. And they suggested a GitHub Action template for Bevy, at ( So, we started on this route.

We were now able to do this, as Ars Militaris is now on GitHub, with the accompanying Ars Militaris Engine. So, we adapted the GitHub Action example that was given to us, and added to it the necessary steps to build a “proper nice MacOS app” listed on Bevy Cheatbook’s MacOS page. And, after some attempts (perhaps the only negative thing we found about GitHub Actions is that there’s no way to test a GitHub Action script before commiting it to the repository, which resulted in a lot of unnecessary commits that “polluted” our commit history), we were able to produce a MacOS release of Ars Militaris, download it from the “artifact”, and make it available on our website.

So, it is with pride that we say that we have a release available for the three major desktop operating systems. If you’re using a Mac computer, you can now download Ars Militaris and do a playtest. Unfortunately, this release hasn’t been properly tested yet, as our MacOS testers were not available, and we are suspicious of a slight bug in this version, that, unfortunately, will cause the game to crash upon entering either the Ambush or the new Multiplayer scenario. But, you should at least see the Main Menu with the Ars Militaris logo.

One of the first obstacles that we found with this release, as reported by a kind user in Bevy’s Discord who performed the first playtest of this version, was that Ars Militaris immediately crashed upon starting. By reading the provided error message, we quickly discovered that the crash was due to Windows-specific code that was in the build. More specifically, it was due to the code that sets up the Ars Militaris window icon when running on Windows. So, we needed a way to disable that part of the code when running on other platforms. Thankfully, the same user who tested the build, recommended that we take a look at “conditional compilation” in Rust. With this, we were able to set up conditional compilation for the problematic code, using the cfg! macro. You can see how easy it was to “disable” that code for platforms other than Windows:

if cfg!(windows) {
    app.add_systems(Startup, set_window_icon);

This piece of code is part of the Bevy App building process, and now, that crash on MacOS is overcome.

After that, we faced another issue, in that, we sent the MacOS build to a friend who owns a MacBook, but, they were unable to run it, as the executable displayed the message “You have macOS 10.15.7. The application requires macOS 12.0 or later” when hovered over with the mouse, and it was not possible to double-click it to start Ars Militaris. Our friend told us it is because their MacBook is over 12-years old. But, we were a bit disappointed as we really wanted them to be able to run the game. Luckily, we had noticed something in the Bevy GitHub Action template that was provided to us. Specifically, it was the lines:

 - name: Configure Environment
   run: export MACOSX_DEPLOYMENT_TARGET="10.9"

We hadn’t included those lines in our build_macos.yml GitHub Action script. So, we thought that by including them, our friend would be able to run Ars Militaris, even on their old MacBook. Unfortunately, they still haven’t be able to test Ars Militaris with this new configuration. But we’re hoping that it will work.

Overall, we’re really happy with having a MacOS version of Ars Militaris, because it is really important to us. Specifically, due to our choice of bevy_quinnet as the networking solution for Ars Militaris, and since QUIC isn’t supported in the browser, we can’t create a WASM release, so we’re going for the native solution, and want players with Macs to be able to play the game.

So, please go ahead and test the MacOS version of Ars Militaris, and please send us a bug report if you encounter any errors.

Fix to nginx log analytics (store logs forever)

While our nginx log analytics solution has been working great, we discovered an issue with it. Namely, we discovered that rhit was only reading logs from 14 days before. So, each day, one of the days would get removed from the nginx log history.

At first we suspected this was the default behavior of rhit, but then, we discovered that this wasn’t the case. Instead, this behavior was due to the fact that the nginx logs are managed by the logrotate.d daemon on our Ubuntu server. And this logrotate.d daemon, which is responsible for managing, you know, “log rotations”, was set up to only store nginx logs for 14 days.

So, we edited the logrotate.d configuration for the nginx logs, at /etc/logrotate.d/nginx, and commented out the rotate 14 line. With this, our nginx logs are now kept indefinitely, which is exacly what we want in order to be able to view the entire website access history.

Now, we know that this means that the logs will start up to take some space in disk, but this is something we will have to manage. For now, it is good enough that our website access history is not being deleted.

New Multiplayer scenario

The highlight of this week has been the development that occurred in the multiplayer aspect of Ars Militaris. This aspect of Ars Militaris is very important to us as it was one of the main reasons why we started developing Ars Militaris in the first place: we wanted to be able to play turn-based tactics battles, like in Tactics Ogre, but in a multiplayer fashion. While there are already some games that offer this experience, we were not satisfied with any of them.

So, in this week we took the work to update the multiplayer aspect of Ars Militaris. Luckily, this work turned out to be simpler than we expected, even if it meant tackling some development tasks which are somewhat complex. The reality is that, because our architecture for the game is sound, we could use the systems that we are using for the single-player aspect of Ars Militaris, in the multiplayer aspect, with only small adaptations. This is really good because it meant that we didn’t have to create much new code in order to support Ars Militaris Multiplayer battles.

And so, available in this release, is the Multiplayer scenario. It is still only available upon request to us, because our server still only supports one battle at a time and has to be restarted after each battle. But, if you have a friend, both of you can start Ars Militaris, choose the Multiplayer option in the Main Menu, and you will be both taken to the Multiplayer scenario. In it, you can do the same UnitActions as in the single-player mode, namely, the Move, BasicAttack, and EndTurn UnitActions.

When performing an UnitAction, you will see that both clients are synchronized with the server, and you will see, for example, the unit moving at the same time on both clients. Similarly, the other UnitActions are also synchronized.

We wanted to have a video showing this synchronization, but, because even though the Move synchronization is visible, the other ones are not so visible to players, as the game doesn’t have literally any UI when in a battle, at the moment. So, we will wait until next week, when we have developed some UI for the battle, to create a proper video explaining Ars Militaris and these details.

Ars Militaris Roadmap

One very important aspect of Ars Militaris which we have been missing is having an Ars Militaris Roadmap. So, here it comes:

We will now explain some of the features that we have planned for the Ars Militaris 0.2 release:

In all three of these aspects of Ars Militaris, we are planning to have them more polished than right now, as we agree that the game is still looking a bit rough on the edges. But, we’re confident that with some work, we can change the game’s look from “prototype” to “alpha”, or something along these lines.

Other news

Bevy lessons

After what are now more than 6 months using Bevy, and after the recent spree in development of Ars Militaris and also in learnings, Lead Developer “cwolf” has decided to now start offering lessons on game development with Bevy, as he now considers himself an intermediate Bevy developer.

These lessons are targeted for beginners to Bevy or to game development in general, as our experience with Bevy has shown us that it is a really easy engine for beginners to pick up. You don’t even have to know Rust in order to start using Bevy, as, when using Bevy, you can start by using a really small subset of Rust, as you will be mostly using Bevy’s built-in APIs, such as the Scheduler, Queries, Resources and States.

So, he is offering the first 2-hour lesson for free. If you’re interested, you can contact him on Discord: @chosenwolf_

My Car

In this week, on Tuesday, I (cwolf) had to go from the vacation house I’m staying at, back to Lisbon to take care of a very important issue related to my car.

Specifically, the reality is that my car was in bad need of attention. About three months ago I had taken my car to a mechanic to get some things fixed. But, that mechanic was very busy, and he couldn’t arrange for the necessary parts that were needed to fix my car. At this point, I could have procured the parts myself in order to help him and have my car ready as soon as possible. But I didn’t do this, and left my car “abandoned” there for more than three months. While I don’t have a great necessity of a car right now, I was using my mom’s car when I needed, but this was something that was not sustainable.

But this week, with help from my father, I went there and got my car back, even though it was not fixed. Instead, it was us that fixed some of the issues that were present in the car (for example, my front-right headlight was broken from an accident I had in January, and I still hadn’t fixed it).

So, now, after I long time, I can enjoy driving my car again, or just chilling by it. I really love my car, because I have a really nice history with it since the moment I bought it. It really is a wonderful feeling to have my car back, and I would like to thank my dad for helping me out with this. Without him, my car would be still left stranded at the mechanic.

In order to share this feeling with you, I chose a song to share with y’all. The song is appropriately titled “My Car”, by Silkk the Shocker, who is one of the younger brothers of Master P. Here you have it:

And, to end, I will show my car. It is a 1987 Nissan Sunny Sedan 1.3 SLX, and it is simply the most gangsta-ass car you will see in your life.

My car

Conclusion and next steps

We’re happy with the progress that occurred in this week, even if we had to take around two days off from Ars Militaris Development in order to get my car fixed. Still, the progress in the multiplayer aspect of Ars Militaris is just great, as now Ars Militaris almost supports complete multiplayer battles. We also now have the MacOS release, which, as we said, is really important to us.

So, the next step is to continue working towards Ars Militaris 0.2. We will try to not have many detours this time, so that we can release a proper Ars Militaris 0.2 when it is time.

So, that’s it for this week’s issue. We hope you have enjoyed, and stay tuned for more Ars Militaris news.

This Week in Ars Militaris VIII

Friday, August 25th 2023

Hello everyone, and good Friday to you. We bring you another issue of This Week in Ars Militaris.

This week started with some administrative tasks, namely, doing a migration of our Ars Militaris server to a new, clean server, and also some upgrades to our website.

We then had the opportunity to, on Tuesday, do some test runs of the current releases of Ars Militaris, both for Windows and for MacOS, due to having access to our friends PCs. With these test runs, we discovered some bugs in Ars Militaris, and we documented them in order to tackle them when we can.

It was also an event-packed week, with two Ars Militaris events taking place.

So, go ahead and enjoy this week’s issue.

Upgrade to web site

The first task that we tackled this week was upgrading our website to make it look a little bit nicer and provide a better experience to visitors.

We were motivated by the fact that, when we posted our weekly post in Bevy’s Discord with last week’s issue of This Week in Ars Militaris, we received feedback from a Bevy user that, while they were interested in keeping up with the project, the website was posing some problems for them. Namely, the fact that one had to resize the browser window in order to have the text to be easier to read (instead of occupying the entire width of the browser window), and also the fact that, because we have our website listing the issues of This Week in Ars Militaris in chronological order, instead of the more usual reverse-chronological order, it was hard for them to follow the project and find the content. They even made a suggestion that we could use, which is just a matter of including this .css in our website with a single line modification to the website source code.

So, we took this opportunity to perform a much-needed upgrade to the look of our website. The first thing we did was to limit the text (and other content) width by specifying a .css property for the body HTML element, with:

body {
    max-width: 1000px;

This already resulted in our website being much easier to read. Well, the truth is that we had always been reading our website in a resized window (with the Windows operating system, just using Windows key + Arrow keys to snap the window to one side while occupying half the screen), but it was foolish of us to assume that visitors would be doing the same.

Then, we created an “index” for the This Week in Ars Militaris issues, that is displayed at the top of the web page, in the “News” section. This index links to each issue of This Week in Ars Militaris, and thus makes it much easier for visitors to navigate the web page.

The last thing we did was to set up two more links in the “Community” section of the website, namely, a link to our GitHub repositories, and also a link to our YouTube channel. This was because the same user that gave us feedback on the website, couldn’t find the GitHub repositories, as, in reality, the only time they were linked to was in the “Open-sourcing Ars Militaris” section in issue V of This Week in Ars Militaris. Now, with these links at the bottom of the page, the GitHub repositories are much easily discoverable.

We ended up not using, because, while we understand and agree that it provides a nice-looking web site, the main issue we found with it was that it changed the font used. And, we have a strong reason for wanting to continue using Times New Roman as the font for our website. While it is not the best-looking font or the easiest on the eyes, we think that it is appropriate that, as Ars Militaris is a game set in the Ancient Rome era, we use a font aptly named “Times New Roman”. Of course, we could set up to use the Times New Roman font, but, by now, we have develop a serious case of the NIH (Not Invented Here) syndrome, and are very cautious about using tools which we don’t understand completely. But, we will still do some more upgrades to the website, in our to improve its usability.

Ars Militaris Server Migration

The second administrative task that we performed was a migration of our entire server to a new server instance. This was an extremely necessary task, as we were suspicious that our server had been compromised. Specifically, we thought that, because we received many visitors while our server was not properly secured, it could happen that someone may had already broken in.

This fear was augmented when we learned about the last command to view the logins at our server, and we discovered some IPs which we didn’t recognize. And, using the tool, we found out that some of these logins were made from locations which we didn’t identified as ours.

So, we decided it was time to create a new server instance, and migrate our entire server set up to it. This included:

We can say that this migration went fairly well, and we only hit one obstacle, namely, the fact that one of our radio station channels (the gangsta channel) was failing to start. This was a problem with ezstream, and one which we find strange, because the other radio channels are working fine, and they use the same configuration. But, because the radio station is not our priority (our priority is, of course, Ars Militaris), we ended up giving up on setting up the gangsta channel for now. Still, we spent some hours trying to debug the issue with ezstream failing to start, with no success.

Perhaps the nicest part about the migration was that we were able to migrate the nginx logs from the old server to the new, and, when we installed rhit on the new server, it could access the entire nginx access history with no problem. This was really cool as it allows us to keep the entire web site access history, which is something we want.

Now, we feel that our new server is much safer than the previous one. Still, we realize we may have made a mistake in our migration, and perhaps this is a serious mistake. Specifically, in order to transfer some of the files, we used scp to transfer them from the old server to the new. And this was done while password authentication was still turned on. So, we think that it is possible that the attacker could have changed the ssh installation to have it send the password used to them in an unencrypted way. We don’t know if this is possible, but it is something we thought of. So, we will still keep an eye on the accesses to the server (by the way, we know that an attacker can operate without leaving a footprint on the last logs, but, it is currently the only way we know of monitoring server accesses).

In the future, we think that when we perform a migration, we will take care so that there isn’t any connection from the old server to the new server. Also, we really should say that we are in great need of a computer/network security expert to guide us some guidance on these issues.

Loading .csv assets into Bevy

Regarding Ars Militaris development, the first thing that we tackled this week was to improve our loading of the .csv file that contains the data about the units in an Ars Militaris battle. These data are the unit attributes such as their HP, Strength, Dexterity, and other attributes, as well as their position on the map, the direction they are facing, etc.

The issue we had with our current implementation was that we were not loading this .csv file with Bevy’s AssetServer. Instead, we were loading it from disk directly with the csv crate Reader::from_path() method. The problem with this is that, we are not sure if the directory structure of a Bevy game stays constant when running on different platforms. Specifically, we were worried that, when packing the game for the macOS platform, and thus having to create the necessary AppBundle directory structure, the running Bevy application wouldn’t be able to find the .csv file in that location. But, we knew that for the Windows and Linux platforms, the directory would stay consistent, as we had been able to test that.

When trying to load the .csv file with Bevy’s AssetServer, we immediately faced an issue where it was not returning a useful object for us to manipulate. We then discovered that Bevy’s AssetServer doesn’t support loading .csv files by default. Instead, there’s a list of file formats that Bevy’s AssetServer can load (available at, and the .csv format (or other formats, such as .txt or .xml, isn’t supported.

We had made a post on Bevy’s Discord #help channel for clarification on this, and another Bevy user suggested that we look into the bevy_common_assets crate, and then after we explained that we were using the .csv file for the unit’s attributes, they recommended the bevy_proto crate. Further along the discussion, when we explained that we also would like to use the .csv format to save the current state of an Ars Militaris battle, they suggested that we could use bevy_save, which is yet another Bevy plugin, and that we could also just use Bevy’s built-in Scenes.

With all these options, we took some time to study them, and arrived at the conclusion that, for our use case and for the current state of the project, we could do with just using bevy_common_assets to load the .csv file. But we quickly discovered that bevy_common_assets doesn’t support the .csv format as well. But, because the crate is documented with good example, we took a look at the example for loading the .xml format, and decided that we could try to patch this crate in order to add the ability for loading the .csv format. So, we decided to do that, but really soon we realized another thing, which is that, we did not like the requirement of bevy_common_assets that we have to create a type that is going to be serialized. We just really wanted a way to have Bevy load our .csv file from the assets folder, in a platform-independent way, so that then we could use the data in that file, without the hassle of setting up the types that we want to serialize.

So, we decided to not use bevy_common_assets for now. This means that we still don’t have a completely tested solution for loading our .csv file in a platform-independent way, as we still need to test if our current implementation will work on a macOS distributable AppBundle. But soon, we will have access to a MacBook from one of our friends, and we will be able to properly test our implementation, and adjust it if necessary.

Ars Militaris Log

We then tackled the feature of having the Ars Militaris Log (a log containing information about an Ars Militaris battle, such as when an unit damages another, when an unit dies, the game start and game over messages, and other information), displayed in the Ars Militaris Console.

Our first idea was to have bevy_log output its log to the bevy_console. Some people had already attempted this, as described on this issue on the bevy_console repository (

So we did our own attempt at patching bevy_log to also output the Bevy’s log into the bevy_console. Our first breakthrough was in discovering that we could add another tracing_subscriber::fmt::Layer to a subscriber, and provide it with our own MakeWriter implementation, with the line:

let fmt_layer_2 = tracing_subscriber::fmt::Layer::default().with_writer(bevy_console_writer);

Then, our implementation for the bevy_console_writer is responsible for handling the sending of the log messages to bevy_console, using its provided PrintConsoleLine event. The implementation was the following:

fn bevy_console_writer(mut print_to_console_event: EventWriter<PrintConsoleLine>) -> impl std::io::Write {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let msg = String::from_utf8_lossy(buf);

    fn flush(&mut self) -> io::Result<()> {

But, we faced an obstacle with this implementation, which was that, in order for bevy_log to have access to the PrintConsoleLine type, it has to depend on bevy_console, and because bevy_console in turn depends on Bevy, this creates a cyclic dependency problem.

At this point, we didn’t know how to proceed to overcome this obstacle, so we ended up trying another solution. But, on hindsight, we think that this could be achieved by splitting the bevy_console PrintConsoleLine type into its own, separate crate, that would only depend on bevy_ecs (as it is the crate of Bevy that provides the Event type). With this, perhaps it is possible to have the PrintConsoleLine type accessible to bevy_log without creating the cyclic dependency problem, but we’re not sure of this. Also, we currently don’t have the ability to do this extraction of the PrintConsoleLine type into its own crate. But, we left a comment on that issue on bevy_console’s repository, describing our experience with this attempt at a patch.

So, we decided to search for another solution. Some time ago, when we were patching bevy_log with the log_file feature, we also got to know about slog, which is another logging crate in Rust’s ecosystem. We knew that with this crate, it was easy to set up multiple “drains” (log outputs).

So, with a little help from ChatGPT, we managed to implement, first, the two drains to match the logging that we already had in our project (the standard, stdout log and the log_to_file log). After some work we managed to accomplish that. Then, we proceeded to implement our third “drain”, which would output to the bevy_console. But we eventually reached a point where we needed the implementation of the Drain trait for our custom BevyConsoleDrain to have access to the PrintConsoleLine events, in order for it to be able to send them. And, because we were setting up the slog logger in a regular Rust function, in the main() function of our app, but before the Bevy App building process (as it is good that the logger is set up before the other steps in the App building process, in order to capture errors that may occur when building the plugins and adding systems), we couldn’t find a way to have the PrintConsoleLine events available to it. But, we then realized that, if we set up the logger in a Bevy system, it would make things much easier as we could provide it with the EventWriter<PrintConsoleLine> type with Bevy’s dependency injection.

But, at this point, we realized something about this feature. Namely, why were we trying to have the entire Bevy log outputted to the bevy_console in the first place? After all, the Ars Militaris Console is supposed to be “player-facing”, and actually should just display information that is useful for players, such as the combat damage and other useful information. So, we put the slog solution aside, and instead just used the regular bevy_console PrintConsoleLine to send messages to it. This means that every time we want to write to the console, we have to add the mut console_line: EventWriter<PrintConsoleLine> parameter to the system in cause, and then have the line console_line.send(PrintConsoleLine::new("Some useful message.".into())). We were trying to avoid this (the fact of having to add another line every time we wanted to log something to bevy_console; instead, we wanted to use our existing info! calls to save some work), but, in reality, this is not a problem.

So, in the end, we opted to keep our current logging with our patched bevy_log, that writes both to stdout and to the logfile, and, for the Ars Militaris Console, just send the PrintConsoleLine messages to it manually. The big learning in this task was that, it is best to make sure the feature one is trying to develop is well-designed, before tackling it. We spent nearly a whole day on this, and it was not necessary. But, we still acquired some very useful knowledge and experience doing this.

So, now, we have already develop a basic Ars Militaris Log that is displayed on the Ars Militaris Console. But, currently our implementation has some issues, related to the fact that keyboard input will still get registered even when typing on the console, and sent down to the game. Also, currently, when the Console window is open, it automatically is focused and the player can’t “unfocus” it. We don’t want this, and are currently looking at a solution for fixing these issues.

UPDATE: As of today (Friday), we made a push in the direction of fixing the described issues, and we can say that we have achieved our goals for the Ars Militaris Console. We will describe our implementation in the next issue of This Week in Ars Militaris.

Ars Militaris Event III

On Tuesday, we visited two of our friends, and we were able to accomplish two tasks. The first one was testing the current Ars Militaris releases on their computers, with the bonus that one of them had a Windows laptop and the other a MacBook.

We started by testing the current Ars Militaris release on the Windows laptop of our friend. And, we were very happy to see that the build started pretty well, with them being able to play the single-player Ambush scenario. But, when they finished playing their turn, and the game turn passed to the AI, a crash occurred. We were not expecting this as we hadn’t touched that AI implementation in quite some time, but, because we changed some of the systems when we updated the multiplayer aspect of Ars Militaris, these changes could have resulted in a modification of the behavior of that part of the code. So, we registered this bug in order for it to be fixed. We also should say that this illustrates an aspect of Ars Militaris development which is not quite well organized, which is the testing of the game. If you are a developer, you should also know that it is quite hard for the developer of a feature to also be its tester, as it is just another task that has to be done and can be quite time-consuming. But, testing the builds is a very important step in the development process, and we are striving to improve this so we don’t release builds of Ars Militaris containing errors that could have been caught by proper testing.

After that, we tested the current Ars Militaris release on our friend’s MacBook. Because it is a 12-year-old MacBook, they hadn’t yet been able to run Ars Militaris with the provided macOS AppBundle. But, we tried to build the current Ars Militaris release directly on his MacBook (we should say here that we were pleasantly surprised with the ease in which it is possible to build Ars Militaris on a MacBook, as almost all the development tools (such as XCode) are already installed). By doing this, they were able to run the executable produced by cargo build, without errors. This was a bit strange to us, because, if they can build and run the Ars Militaris executable produced by cargo build, why can’t they run the packaged .dmg AppBundle (they encounter the error message: You have macOS 10.15.7. The application requires macOS 12.0 or later``)? This seems to be problem with either the bundling of the application, or the fact that the AppBundle we provided has a step to it where we use thelipotool to produce a single-executable from the two targets for themacOSplatform:x86_64-apple-darwinandaarch64-apple-darwin`. Perhaps this latter aspect is the issue. Soon, we will be able to finally test this issue, and possibly overcome it, as we would like for Ars Militaris to be playable even on old MacBooks.

But, with the build that our friend built himself on his MacBook, we were able to test another aspect of Ars Militaris, namely, the Multiplayer aspect. But, as soon as we started to test it, we were faced with an error:

2023-08-22T20:12:13.342749Z ERROR amclient: Panic occurred: PanicInfo { payload: Any { .. }, message: Some(Failed to create client endpoint: Os { code: 42, kind: Uncategorized, message: "Protocol not available" }), location: Location { file: "/Users/{username}/amengine/bevy_quinnet/src/client/", line: 499, col: 50 }, can_unwind: true }

This error message seems to say to us that the QUIC protocol is not available on that version of MacOS. At least that is what we think, because, we would be really sad if bevy_quinnet didn’t work on macOS, as it is the most important crate in our game, as it enables the Multiplayer functionality. But, in about a week or two, we will have access to a more recent MacBook, and will be able to debug this issue.

After these testing sessions, we then took to playing a battle of the Ars Militaris board game version. We had brought our new board with us, even though it is not completed yet, but we decided that it would be good to do a first playtest of this new board, to see if it was suitable for an Ars Militaris battle. So, we had our two friends play against each other. One was controlling the Romans, and the other the Celts (these are the two armies we have available as of now).

The battle was actually one of the most epic Ars Militaris battle in history. We will share here somewhat of a battle report:

So, the rules for the scenario were the following:

Both players made their deployment at their locations on each side of the map. Then, the battle started.

Initially, the Celts had the initiative, due to their higher Movement Range, and they started attacking the Romans. But, they were a bit lucky in the dice rolls, as, because they have a very low defense value (after all, they are Naked Fanatics who literally fought naked), it is very hard for them to make a successful defense roll, but they managed to defend many attacks by the Romans. With this, they started getting an advantage in numbers once they had killed a few Roman units.

At this point, it seemed that the Celt player was going to win, as they had more numbers. But, something epic happened. The Celt Chieftain (leader) engaged into combat with the Roman Captain (also the leader). The Roman Captain was surrounded by enemies in a corner of the map, but he made an heroic Last Stand, and, at the last possible moment of the battle, when it was about to finish, he managed to deal a killing blow to the Celt Chieftain, thus winning the game for the Roman player. And this was also after the same Roman Captain had dealt the killing blows for every Celt unit that was killed.

We were really happy with this outcome of the battle, not because the Roman player won, but because it showed that, in an Ars Militaris battle, there’s still chance for a player to win, even if the odds seem against them. This is a nice feature of Ars Militaris as it allows for more fun, as the game is not decided until the very last moment.

The only negative aspect of this playtesting session was that we didn’t took any photos. Instead, Lead Developer “cwolf” was busy being the Arbitrer of the battle, in order to facilitate the understanding of the rules by the players and the flow of the battle.

Interview at Funcom

Some time ago, I was randomly browsing through my personal Instagram, and noticed that a colleague of mine from high-school had posted a story where she showed some merchandise with the Funcom logo. We already knew Funcom, as the developers of Conan: Exiles and other games, and we thought that perhaps our friend had started to work there.

Also, some time ago my father gave me the advice that I could look for something like an internship, in order to further my knowledge of the games industry, and how to develop and operate a professional game. Because some times in my life already, following my father’s advice resulted in very positive things, we decided to heed his advice, and decided to message our friend to see if she was really working at Funcom.

But, she got married and was in her honeymoon, so, being the gentleman that I am, I decided to wait until the honeymoon was over before messaging her, in order to not disturb her with work-related things in a so special time.

When I finally messaged her, she confirmed that she had indeed started working at Funcom, as a producer. I then asked if she knew about any internship positions at Funcom, as she replied with a link to a 3-month internship as an Assistant Producer at the Funcom studio in Portugal. Once I read the job description, I was hyped as it seemed to me that it would be perfect for me, as it would allow me to gain the professional experience in the games industry that I strongly desired. Also, the 3-month time frame was optimal for me, as I didn’t want a long-term commitment.

So, I applied, and on Wednesday had the interview with them. In my opinion the interview went really well, they were very interested by my experience in developing Ars Militaris as mostly a one-man-army, and also by my usage of non-standard game development programming languages, such as my usage of the R language in the last prototypes of Ars Militaris, and now the usage of Rust and Bevy Engine. I also believed that my past experience as a Software Engineer at the previous company I worked for would prove valuable, even if the position I was applying to was in a different role, with different tasks. But I believed my experience would transfer to that.

But, today I received an email from Funcom saying I wasn’t selected for this position. This left me a bit disappointed, because I was really hoping for this experience, as I believe the knowledge I would gain from working with them, would then transfer to the development and management of Ars Militaris. But perhaps this was the exact issue with my application. I feel that perhaps they considered that I was too involved with the development of Ars Militaris to be able to focus on their game (they are currently developing Dune Awakening, an open-world surviving MMO set in the Dune universe). And perhaps they are right, after all. I was honest with them and told them that my dream is to have Ars Militaris developed and to run the company that will manage the game. And I think that they were looking for someone with other goals for this position.

In the end, it is always a bit hard to face rejection like this, but, besides that, I’m not entirely unhappy. The reality is that, while I would surely learn a lot while working there, it would take my precious time away from Ars Militaris development, and would result in the postponing of our planned roadmap and release dates. Also, I don’t feel I was completely rejected, as, for the first time in my life when dealing with other companies in the games industry, my experience as an independent game developer for over 9 years now was valued. For that, I am thankful to Funcom, through the interviewers, for showing interest in Ars Militaris and my journey with it.

My conclusion is that perhaps this internship was not right for me. So, I feel that God has taken action to protect me and Ars Militaris from what could have been a step in the wrong direction. I now feel free to continue working on Ars Militaris at my own leisure, and, because things are going so well, it makes me happy that I continue progressing through its development.

Ars Militaris Event IV

Soon after I arrived at my family’s vacation home, I went to the local barber to get an haircut. Then, you know, in the usual barber conversation, I casually told him about Ars Militaris. He then mentioned that he knew some friends that were board game addicts, and hosted weekly board game meetings in this town. He even said that perhaps they would want to buy the board game version of Ars Militaris.

So, he gave me their contact, and I messaged them, asking if I could showcase the board game version of Ars Militaris to them. So, yesterday (Thursday), I went to their meeting and brought the board game version of Ars Militaris with me (both the “pristine” Ars Militaris board, and the new board that we’re developing, that will be the first board that we will sell).

At first, I played two matches of “The King Is Dead”, which is a very fun strategy board game. Each match took less than 30 minutes, and I can say I benefitted from beginners luck, as I won both of the matches while having never played this game before. After that, I invited the players who had played with me to try Ars Militaris.

So, we did a playtesting session, in the new board. And it was very fun. This time I played, as the Romans, against my opponent with the Celts. Because he was an experienced game player, it only took about 10 minutes or less to explain the rules, and we could start playing. The battle then took about 30 minutes, and resulted in a loss for me. This was actually surprising to me, as, because I have been watching a lot of playtesting sessions of Ars Militaris, I thought that I knew exactly what I needed to do in order to win.

So, my initial strategy was to send my strongest units, including the Roman Captain, forward to the center of the map, and establish my position there. But I didn’t take into account that the Celts have a high movement range, and so, my Captain was attacked and damaged already in the second turn of the battle. Because we were playing with the rule “Kill the Leader”, where if a player’s Leader dies, he loses the battle, I then had to retreat my Captain to a safer position, and have my other units protect him, by occupying the tiles from which the Captain could be attacked. But, this meant that I couldn’t use my units to attack the enemy units.

Still, I then managed to win some skirmishes, and kill most of his units. But, my Captain was badly wounded from the initial damage he took, and he was at only 1 HP, and had already made some miraculous saves, which if unsuccessful, would have resulted in me losing the game. And this is exactly what happened, when his last Celt Naked Fanatic Spearman moved into range and dealt the killing blow to my Captain, thus granting the win to my opponent, when the game state was actually becoming favorable to me.

It is somewhat funny that I lost the battle, because I was really confident in my ability to play Ars Militaris. After all, I’m the game designer of this game. I should know how to play it. But I really felt like a noob, because I did some big mistakes, and this was an humbling experience.

I am also very happy that my opponent enjoyed the battle, they said that it was a “light” game (when compared to other, more “brain intensive” games), and they made some suggestions regarding the rules, one of which we are actually thinking about incorporating into the game. So, we are grateful for the opportunity to be present at this meeting with our game, and now know that we can come back any time we are in this location.

Here are two pictures of the final state of this battle:

The final battle state
The Celt Naked Fanatic Spearman who delivered the killing blow to the Roman Captain

echo Poem

For the last section of this issue, I bring you a creation of mine, which is somewhat personal, but which I really like, and I feel that the time has come to share it with the world.

It is a poem, dedicated to the love of computers, and computing in general.

It is called the echo poem, and it is a short, four-line poem. Here it is:

With echo I talk,
And with echo I walk,
These computer wayz,
My best days.

I now will give an explanation of the poem.

“With echo I talk,” means that you can use the UNIX echo tool to send text to standard output, so, you are “talking” to the computer.

“And with echo I walk,” is referring to the fact that, using the UNIX pipe, you can start command chains with echo, and thus with these command chains you are “walking” the “computer wayz” (wayz with a ‘z’ to be a little bit gangsta).

“My best days.” is a statement to the love and joy that one can get from using the computer. I think this is pretty much self-explanatory.

I’ve created a repository for this poem at GitHub.

This is by no means an attempt at fame. It is just a sharing of a creation which I enjoy and which I myself find beautiful.

Conclusion and next steps

This was an action-packed week, with developments in many different aspects of Ars Militaris. Because we are tackling these many aspects at the same time, this results in that a single aspect of the game doesn’t advance as quickly as it could if we would focus on that single aspect.

But, we enjoy working this way, and we also have our reasons for doing so. For example, we just love the Ars Militaris board game version, as in our opinion it is a one-of-a-kind board game, and we have never seen anything like it. It also gives us great pleasure in working with physical materials, such as wood, paint, miniatures, cards, and other props that make part of the board game version.

Still, some progress has been made in the digital version of Ars Militaris, and also the website and our server security. These progress should be taken into account now that we’re evaluating this past week.

Regarding next steps, we still have two weeks until our planned release of Ars Militaris 0.2. We hope that in these two weeks we can implement the features we have identified, that will result in Ars Militaris 0.2 being the first version of Ars Militaris that we call “playable”. This means that we will focus some of our resources into “polishing” the digital version of Ars Militaris, to offer a more pleasant experience to our players. With that being done, we can finally be confident in creating some gameplay videos, and also start playtesting the digital version of Ars Militaris with more people.

Regarding the board game version, we are currently waiting for an order of some raw materials that are necessary to produce the boards. Once they arrive, we will start producing them.

We also have made progress in another aspect of Ars Militaris, which is the Ars Militaris Development Diary. Specifically, we are now about 2/3 into cleaning the diary from personal, sensitive information, so that then we can publish it. This is something we really look forward to, because, even though we don’t know if people will find it interesting, this diary is something we are very proud of, as it contains very high-quality, computer-usage learning material.

So, stay tuned for more Ars Militaris news!

This Week in Ars Militaris IX

Sunday, September 3rd 2023

Welcome to this week’s issue of This Week in Ars Militaris. This week’s issue comes a little bit later than usual, but in Portugal we have a saying, “Better late than never”. So, this week’s issue starts with another small but significant improvement to our website. Then, we describe our solution to the issues we were facing with the Ars Militaris Console. After that, we bring you the main feature of this week: the development of the Ars Militaris Lobby, along with some troubles that went with it. We finish with a review of our roadmap.

Hope you enjoy this week’s issue!

Compressing website images

Some time ago, we had taken notice of a small issue with our website. Which is that, after we published the first photos of the Ars Militaris board game, they were quite large in size, about 2.5MB each. And, because there were 10 of them in Ars Militaris Event II, this resulted in an at least 25MB download every time a visitor visited the website. This was not a problem on fast connections and the images would still load instantly, but on slow connections they would load really slowly.

We knew that there were ways to compress images for displaying on the web. So, we searched and found TinyPNG, which allows one to freely compress images. We compressed the images on our website, and achieved over 90% compression on each one. This means that each image is now at 300KB max, which results in much faster loading times, and less bandwith usage.

The bandwith usage was proving to be a problem also, because, since This Week in Ars Militaris started being included in This Week in Rust, we started to receive some traffic, and, on the day when we reached our record number of visitors, the server bandwith usage actually got to 100%, which is not good as it means that some visitors perhaps were not able to access the website at that time.

So, overall, this small improvement is actually quite significant as it brings about several benefits to our website.

Complete Ars Militaris Console

In last week’s issue we had described how we had achieved our goal of “shoe-horning” bevy_console into the Ars Militaris Console. Our main goal was to have the console always open during an Ars Militaris battle session, and then the player would be able to issue commands in the console, and also the console would display the battle log. By last Friday, this goal had been achieved, as we described, but we were still left with some issues.

The first one was the fact that the default behavior of bevy_console is defined so that when the console is open, it is automatically focused and the player can’t unfocus it. We really needed for the player to be able to unfocus the console, or rather, that the console would be disabled by default, because we still want the player to able to interact with the game while the console is open.

The solution to this was actually kind of surprising, because initially we weren’t going for that route. Initially, we thought that we had to modify an has_focus field somewhere in the egui EguiContext. But then, after some time, we realized something. Because egui is an Immediate Mode GUI framework, this means that the UI is redrawn every frame. So, it is actually pretty cheap to draw the UI. This means that we could just conditionally draw the bevy_console egui window, based on if the mouse cursor was on top of it or not (with the ctx.is_pointer_over_area() method from egui), and then define its TextEdit::single_line’s .interactive field, so that the console text input field is only editable when the player moves the mouse cursor to the console window. Now, the console window doesn’t remain focused anymore by default, and it is only activated when the players wants it to.

The second issue was the fact that the player’s keyboard input would “pass down” from the console to the game even while the console was open and focused. This is a known issue with bevy_console as documented in its repository Issue #2. This was also not acceptable and we needed a way to fix this behavior. Luckily, there were a lot of solutions proposed in the comments to that Issue, and by studying them, we are able to overcome this issue. Specifically, we used the ctx.wants_keyboard_input() method (from egui), and created a new variable in the ConsoleState bevy_console Resource, console_is_focused, which is just a bool that is being set every frame to the value of ctx.wants_keyboard_input(). Because this value actually returns true every time the console’s TextEdit is focused (and thus waiting for keyboard input), we could now use this new variable to track the state of the console. But, in order to do that, we still had some trouble because bevy_console’s ConsoleState Resource was not public. So, we had to make it public. After that, we can, in our game, when we check for input, also check if the console is currently focused (by accessing it with console_state: Res<ConsoleState> and then in our game input we have to check it also, like this:

if input.just_pressed(KeyCode::W) && !console_state.console_is_focused {
    // Handle pressing of W here...

In reality this is a bit cumbersome (to have to add this check every time we want to define keyboard input), but, because the Ars Militaris Console is a major part of Ars Militaris, we decided that it was not too bad a situation.

So, with these two fixes, we now have the Ars Militaris Console behaving exactly as we want it to. That is awesome and means that we can continue using it for the stated purposes of allowing the player to enter commands into the game, and also displaying the Ars Militaris Log. Also, patching bevy_console with this new behavior and the work is included resulted in an increase in knowledge about both bevy_console and also egui, and also general knowledge about patching a crate to fit one’s exact needs.

We have not yet made available this patch of bevy_console, as we are somewhat in the middle of a development sprint and haven’t had time to update the Ars Militaris repositories yet. But it will be available within the Ars Militaris Engine. We also plan to leave a comment on bevy_console’s repository with our experience with these issues.

Ars Militaris Lobby

The main development that occurred this week was the start (and almost completion) of the development of the Ars Militaris Lobby. The Ars Militaris Lobby is responsible for having the players connect to it (when they press the Multiplayer button on the Ars Militaris Main Menu), and managing the creation and joining of lobby rooms by the players, and also the creation of a game server for a battle session.

Before starting this new development, we should say that we had already decided on an architecture for this aspect of Ars Militaris. Namely, we had decided that we would have a “central” Ars Militaris Lobby server (amlobby), and this amlobby would then spawn “micro” amservers once the players had set up their lobby room and press the “Start battle” button.

So, development started on a fresh, completely from scratch project, amlobby. This was still supposed to be a Bevy App, in order to be able to use bevy_quinnet, and it would run in headless mode in our Linux server.

100% CPU Usage

Immediately we were faced with an issue. For some time, we had noticed that, if we left the amserver running for a long period of time, we would get the warning message Changes older than 3258167295 ticks will not be detected., and also the server CPU usage would increase to 100%. We had somewhat ignored this problem, but now, when we ran our new amlobby with just a blank bevy_quinnet server implementation, we noticed the CPU usage immediately jump to 100% upon starting the process.

We became very worried by this, because, it meant that perhaps we had ignored for so long an issue that was important. We had this issue listed on our bug tracking system (which is really just an ars_militaris_bugs.txt file), for more than a month now. So, we started to try to debug this issue.

The first thing we did was to set up a new Bevy test project and have it long-running locally to see if the same Changes older than 3258167295 ticks will not be detected. warning message would show up. After about two hours of having the test running, without the message showing up, we kind of gave up on this test.

By this time, we had also posted on Bevy’s Discord for help, both on the #networking channel, and also on the topic for bevy_quinnet on the #help channel. After some time, we received some help, which was fundamental in solving the issue we were facing. Specifically, the issue was that, when running a Bevy App in headless mode, only with the MinimalPlugins, the default ScheduleRunnerPlugin is set to run at infinite ticks-per-second by default. This was causing the server CPU to run at 100% to keep up with the infinite FPS. This is actually described in Bevy’s official headless app example:

// This app loops forever at 60 fps
                1.0 / 60.0,
        // Other plugins and systems...

We just didn’t pay attention to that detail when we set up our server application to run in headless mode. Once we set up the tick-rate limit to be 60 FPS, the 100% CPU usage was gone (it was in fact at 1%). We were very relieved by this as we were worrying that this issue would prove problematic and hinder our progress. But, fortunately, that was not the case. Also, the users that helped us in Bevy’s Discord also mentioned that the Changes older than 3258167295 ticks will not be detected. is just a meaningless message, so we became less worried about that as well.

In the end, it was really a great feeling that we could continue developing the Multiplayer aspect of Ars Militaris, using bevy_quinnet, as the Multiplayer aspect of Ars Militaris has become quite important by now.

Setting up amlobby with Ars Militaris Console commands

Once the 100% CPU usage was overcome, we were able to continue making progress in this development. So, we took to develop some commands to be used from the Ars Militaris Console to help with the creation and connection to lobbies. So, we created the following commands:

We should note that these commands were created on the amclient (Ars Militaris Client), and each of them will send a specific message to the amlobby, which will respond with the correct data they need. With these commands, we were able to test our implementation of the amlobby, and we can say that the implementation turned out pretty successful.

Creating an UI for the Lobby Browser

After we had tested the implementation for the Ars Militaris Lobby with the Ars Militaris Console commands, it was time to create an UI for it. We decided to use bevy_egui for it, because by this time we had gained some experience in using egui from messing around with bevy_console, and we also had experience with Immediate Mode GUI, when we were developing the Ars Militaris Prototype in Unity and developed our first Editor script and tools.

Currently, we’re in the middle of the process of developing this UI. We already have the main screen of it, showing, on the left panel, the player’s username with an option to change it, then, in the central panel, the lobby list will all the rooms and the players in them, along with a button to join that lobby, and then on the right panel, the number of currently connected players, and below it the list of the connected players.

This lobby system takes inspiration from the Lobby Browser of Voobly, which was for a very long time the main place where you could play Age of Empires II: The Conquerors in an online competitive manner. We had a great experience with using Voobly, and in reality it is impressive that a team of volunteers could provide a better experience than even Microsoft themselves provide in Age of Empires II: Definitive Edition.

So, here is a screenshot of the main UI section of the Ars Militaris Lobby:

Ars Militaris Lobby

Spawning an Ars Militaris game session

The next step in order for the development of the Ars Militaris Lobby was to have the amlobby server, upon request by the players, to start an Ars Militaris multiplayer game session (with the amserver), and connect the players to it. This was already somewhat of a complex feature, as it involved the amlobby process creating amserver sub-processes. So, we will explain the complete architecture of this feature:

  1. The players connect to the Ars Militaris Lobby, create a room, and press the “Start Game” button (or use the start-lobby command).
  2. The amlobby server searches for open ports between the range 6000-7000 (excluded), and, once it finds an open port, creates an amserver subprocess, listening on the specified port, and sends a message to the clients that started the game in that specific lobby with the battle server port number.
  3. The players connect to the battle server and start the battle.

Here’s the full code for part 2), when the amlobby receives a StartGame message from one client:

ClientMessage::StartGame => {
    info!("Received StartGame message from player {}.", client_id);
    // Check if there are already two players in the room.
    // Get the player's current lobby room.
    if let Some(current_lobby_id) = lobby_data.player_rooms.get(&client_id) {
        if let Some(lobby_battle_data) = lobby_data.lobbies.get(&current_lobby_id) {
            if lobby_battle_data.players.len() == 2 {
                info!("There are two players in the room.");
                // Start a game server for the session.
                // Find an available port.
                let output = Command::new("sh")
                    .arg(r#"netstat -tuln | awk '$4 ~ /:[6][0-9]{3}$/ && $4 !~ /:7000$/ {split($4,a,":"); print a[2]}'"#)
                    .expect("Failed to execute command")
                    .expect("Failed to capture stdout");
                let mut first_available_port: u16 = 6000;
                let reader = io::BufReader::new(output);
                let mut lines: Vec<u16> = Vec::new();
                for line in reader.lines() {
                    if let Ok(port_str) = line {
                        if let Ok(port) = port_str.parse::<u16>() {
                            //println!("Port in use: {}", port);
                if lines.len() == 0 {
                    // Start game session on port 6000.
                } else {
                    loop {
                        if !lines.contains(&first_available_port) {
                        } else {
                            first_available_port = first_available_port + 1;
                if first_available_port >= 7000 {
                    info!("Server is full. Can't create more battles.");
                // Start game session on port computed.
                info!("Starting new game session on port: {}.", first_available_port);
                let output2 = Command::new("sh")
                    .arg(format!("../amserver/amserver -p {}", first_available_port))
                    .expect("Failed to execute amserver");
                // Assume server has correctly boot up.
                // Send a ConnectToServer message to the players.
                info!("Sending ConnectToServer ServerMessage to players...");
                for player in &lobby_battle_data.players {
                    endpoint.send_message(*player, ServerMessage::ConnectToServer {
                        port: first_available_port,
                    info!("Sent ConnectToServer ServerMessage to player {}, with port {}.", client_id, first_available_port);
            } else {
                // Only one player in the lobby.
                // Start battle with second player as AI.
                info!("There is only one player in the room.");
                // TODO: Implement battle with second player as AI.

In our opinion the most interesting parts are the usage of std::io::Command to spawn the subprocesses required for handling this behavior. First, we start a pipeline using the netstat tool to find the ports that are in use, which is then fed into awk to filter those between port range 6000-7000. After that, we make some computations to determine what is the first available port available in that range, and, then, we again use std::io::Command to spawn the amserver subprocess that will handle that Ars Militaris multiplayer battle session, providing it with the specific port through a command-line argument. When the amserver is spawned, the amlobby then sends a ConnectToServer message to the clients in that lobby room, with the port on which they will connect to.

We should also say that, in order to accomplish this, it was necessary for the amserver to have the ability to accept the port number as a command-line argument. This was done using the clap crate, and included simply defining a define_args(), which contained the following:

fn define_args() -> clap::ArgMatches<'static> {
    clap::App::new("Ars Militaris Server")
        .about("The official Ars Militaris server.")
                .help("Sets the port number")
                .default_value("6000"), // Set your default value here
        // Add more arguments as needed

Then, right at the top of the main() function, it was just a matter of having these two lines:

let args = define_args();
let port = args.value_of("port").unwrap_or("6000").parse::<u16>().unwrap();

And then configuring the port in our custom Game Resource:

app.insert_resource(Game {
    port: port,

Overall, we can say that we are pretty happy with this development of the Ars Militaris Lobby. While it still has some details left, it is already in a pretty usable state, as it allows the setting of a player’s username (we aren’t dealing with passwords yet because of security concerns), the creation and connection to a lobby room, the display of the current lobby rooms and their players, and also the ability for sending players from a lobby room to a multiplayer battle game session. This is accomplished using what we think is a sound architecture that has a clear separation of concerns, with the amlobby project handling only what is stricly required of it.

It is also of note that the Ars Militaris software family has now grown: before it was three projects (amclient, amserver, and amengine), and now we have the addition of the amlobby project to the family.

This development of the amlobby is also crucial because it will now allow us to test a very important (and basic) feature of our game, that is, the ability for handling multiple game sessions at the same time. Before this, each time we wanted to run a multiplayer playtesting session, we had to connect to our server, start the amserver, and then, after the testing session was over, shutdown the amserver. Now, we will be able to have the amlobby long-running on our server, and, when we want to test the multiplayer aspect of Ars Militaris, we can just create a new lobby room and start the multiplayer session from there. And the amlobby is now capable of starting multiple game sessions.

Reviewing our Roadmap

With the mentioned developments in the Ars Militaris Lobby, we are confident now that we will be able to accomplish our stated roadmap. Also, we have now made the decision to focus solely on one aspect of Ars Militaris, for now. We chose the Multiplayer aspect, for several reasons.

Regarding the Single-Player aspect, there arised a big problem. Because our first content would be a “tutorial” campaign, and because for that we wanted to use a short-story written by an established author, we haven’t been able to contact them yet to try to obtain the rights to use their story for Ars Militaris. But, we’re trying hard for this, because for a long time we have idealized how cool it would be to have that story in Ars Militaris. And, the other content we have planned are all long campaigns, which we simply don’t have the resources to develop right now.

Then, regarding the Board Game aspect, a problem also arouse, which is that, this aspect of Ars Militaris requires a lot of financial investment in raw materials and other production costs. So, at this point, it was impossible to keep going with this aspect of the game, but we will keep you updated as things may change.

So, we’re left with the Multiplayer aspect, which is actually the aspect that Ars Militaris initially started for. And, in that regard, we’ve actually made good progress, now with the Ars Militaris Lobby, and with the integration into the Multiplayer aspect of the developments that had occurred in the Single-Player aspect some time ago. This means that the Multiplayer aspect is up to speed with the latest developments in Ars Militaris. So, now, it is a matter of focusing on it, build upon the solid architecture that is in place, and start polishing the game so that it can be more pleasant to players.

So, the plan is release Ars Militaris 0.2 next week. We will add some polish already to the current features, and also complete the development of the Ars Militaris Lobby, and fix some bugs in its interaction with the Ars Militaris Server. So, we intend that this release will provide somewhat of playable, multiplayer experience.


We’ve already outlined some of our next steps in the section above. So, we conclude by saying that Ars Militaris development is currently being hindered by the fact that 100% of the work is being done by a single person. So, we’re continuing to look for collaborators to join the Ars Militaris Dev team. This has been a too-extreme lone wolf game development journey already. But we’re confident that our work in finding help will prove successful.

So, thank you for reading this week's issue, and stay tuned for next week's issue, where we will bring big news!