Milestone: Villages

screenshot0008.png

Almost one year ago I started on this project. It still looks promising, I’ve found work-arounds for all road blocks and nearly all abstractions are in place and working. That means I from now I build on code I’ve written myself. No one is left to blame except the guy in the mirror.

Why is this a milestone? Well, running the demo is clearly not impressive, but is proves a few important things:

screenshot0010.png

The last point deserves expanding: The current 0 A.D. SVN was just updated from SM 24 to SM 31 and performance improvements are highly visibly. At first I thought the internal profiling broke, because it reported “0 msec” far more often than usual, but that was not the case. The initialization of an instance of Hannibal now takes around 30-40% less time. I have to make separate tests, find out what changed and report back here. One thing cannot be repeated often enough: Make use of function inlining!

Here’s an example:

  obstructions
    .blur(radius)
    .processValue(v => v < 32 ? 0 : v)
    .addInfluence(coords, 224)
  ;

It works on the grid objects which support method chaining. The arrow function processValue() throws at the grid is called on every pixel and that line takes less than 1 msec for a 512x512 map on my years old machine. There is clearly no function overhead involved and I even started to review a few modules to exploit this and achieve more readable code in the process.

screenshot0012.png

By now you can see the village has no structure and buildings are randomly rotated. The algorithm at work is a fail safe. It can find a place close to a given point if there is at least one available. Building a village is a packing problem and these suffer from NP !== P. I haven’t found a fast one for rotated rectangles yet, but the separating axis theorem is useful. So, Hannibal can try to layout its village and choose the fail safe as last resort. Actually there are not that many requirements: Fields should be very close to a dropsite, towers are best organized as corners of an equilateral triangle and on some maps the concept of streets is needed to avoid blocking the exit points of a village. And eventually if terrain allows a strong wall.

screenshot0014.png

So here’s my road map to the next test release:

Actually I plan to make this a full release which supports the sandbox difficulty. Sandbox means Hannibal will not attack and new player can spy on the bot to develop the micro-management to build a village fast.

The release after that might even include ships :)

I’d like to stress here Hannibal is Open Source and everybody is welcome to contribute. Conceptually it is a Bot Development Kit for 0 A.D. with an engine and autonomous groups running on top. The groups are scripted with an easy language. This test release is about building a village and here is the most important piece from the builder group. It is called when the economy found a place for a building or assigns a unit to the group.

  // a request was successful

  }, assign: function assign (w, item) {

    w.objectify("item", item);

    // keep requesting units until size
    w.units.on
      .member(w.item)
      .lt(w.units.count, w.units.size)
      .request()
    ;

    //  the first unit requests structure to build, exits
    w.units.on
      .member(w.item)
      .match(w.units.count, 1)
      .match(w.buildings.count, 0)
      .buildings.do.request() 
      .exit
    ;

    // got the foundation, all units repair, exits
    w.buildings.on
      .member(w.item)
      .match(w.item.foundation)
      .units.do.repair(w.item)
      .exit
    ;

    // got the building, check order next, exits
    w.buildings.on
      .member(w.item)
      .match(!w.item.foundation)
      .lt(w.buildings.count, w.buildings.size)
      .request()
      .exit
    ;

    // got unit, send to repair
    w.item.on
      .member(w.item)
      .gt(w.buildings.count, 0)
      .repair(w.buildings)  
    ;

You’ll find me at the 0 A.D. forum. Many thanks to everyone active over there.

 
27
Kudos
 
27
Kudos

Now read this

Simple Lists with ES6/Harmony Proxies

If you are into meta programming proxies are the most outstanding addition to JavaScript. Together with apply(), call() they allow to nicely abstract from build-in features and help to create domain specific languages. I was in need of... Continue →