Crosshairs

May 24, 2009

Finally, after a lot of internal changes, you can tell if a unit can be attacked by holding the mouse pointer over it. A red crosshair will appear over it until you move the pointer away again. Here is a screenshot:
screenshot-090524-1

The mouse pointer doesn’t appear in the screenshot for some reason, but I was holding it over the crosshair. The selected unit is indicated by a sharp border around its hexagon, and the hexes it can move to are highlighted, just like before. The tank isn’t really supposed to be able to cross the strait in one turn, but I haven’t yet bothered to update the terrain graph completely after I made changes to the hex grid.

Another change that can be seen in the screenshot is an anti-aircraft unit, near Copenhagen. I haven’t written any code for it yet though, so it behaves like a tank :)

To accommodate the crosshair functionality I wrote a simple quadtree implementation which can map mouse clicks to scene graph nodes quickly. The new code is about 700 times faster than the old one, which searched through the entire scene graph including terrain and all. Working at this made me realize a lot of things about scene graphs and how they should interact with other parts, which will probably help when I set out to speed things up later. Currently there’s an annoying lag when you do many things that require updating the window, because I redraw too much stuff.


A Year has Passed

May 1, 2009

It has been a year since I posted the first screenshot (on another blog), which is the earliest recorded sign of activity on the game. I can not say exactly when I started, but it seems I have been working on it for about a year now. I have been pretty serious about the game since my vacation last July, much of which I spent coding. That was when the tinkering transformed into an attempt to write a complete game–a product.

Here is the old screenshot along with a fresh one for comparison (click for full size). I’ve come a long way since then.

screenshot-11

screenshot-090501

I have fixed many bugs and shortcomings in the SVG parser recently. Editing the graphics is now much more comfortable, since you can use more SVG features and don’t have to trick Inkscape out of using previously unsupported features such as transformation matrices.

The source code is now 6435 lines, of which 3983 lines are C++. The rest is Scheme code. The count includes comments and blank lines, but not header files. There’s some dead code too that could be deleted, but not much.


Progress and Plans

April 13, 2009

I have improved some more interface details. Now, when you select a unit, the borders of its hex become thicker until the unit is deselected again. Another change is that units now turn in the direction you move them, so a tank that has just been moved from west to east will face east, for instance.

I’ve been thinking about announcing an early preview version of the game on some Internet forums for feedback, and which features should be included in that case. I don’t want to send out a crappy game with a bunch of half-finished features, but I don’t want to wait until everything is perfect either. Right now, I’m leaning towards trying to get something simple out late this summer.

The features I think must be included in the preview are:

  • One relatively large and good-looking map, of let’s say Denmark, with shifting terrain etc.
  • There must be some visual indication that a unit can be attacked by the currently selected unit. Panzer General put a cross hair around it if I recall correctly.
  • Deployment and movement of lots of units must work flawlessly since you will be doing it a lot.
  • The bombers must be counterbalanced by for instance air defense units.
  • I must either adjust the hex grid to the terrain or the terrain to the hex grid so that it is always clear if a hex is a land or a sea hex, for instance.

That is it, I think. The other stuff either works already or is not essential. I may be forced to include zoom too when I increase the size of the map if it becomes too hard to get an overview of the field.

The preview version probably wont be much fun to play without sound, animations or surprises, but at least I’ll have something to show. There won’t be anyone to play against anyway, since there is no AI and no server :) You will have to sit next to your opponent.


Bombers can now Bomb

April 10, 2009

I’m back to hacking on the game again. I’ve made the bombers able to attack and polished some small things, like how units and flags are arranged inside hexagons.

As you can see, the map is also bigger now, and the panel is placed at the top of the window and contains more buttons. The “toggle view mode” button changes between air mode and ground mode, ie which unit is scaled down when an aircraft shares hex with a surface unit. I know the buttons look awful but fixing that can wait.

screenshot-090410


Layout Language

February 8, 2009

To my surprise, I didn’t get any error messages any longer after I stopped using multithreading. All I had to do to fix it was catch all exceptions from the evaluation loop and call a function to print an error message when an exception was caught, but I didn’t realize that at first. Instead, I wasted many hours fighting with Chicken. I got tired and frustrated and didn’t get as much work done as I had hoped.

However, I did start hacking on a sublanguage for automatic layout of user interface components. The idea is that you should be able to specify a layout using a clean declarative language, much like HTML or Mozilla’s XUL. That way you don’t have to write as much code to arrange buttons and the like, and the specifications will be much more readable and easier to change than imperative code.

Here is an example of the kind of declaration I’m aiming to support:

(hbox (width: 100 %)
  (hbox (align: left) ship tiger stuka)
  (hbox (align: right) end-button exit-button))

A hbox is a container that arranges its components horizontally, from left to right. In this case, there is a hbox that contains two other hboxes. One of them is left aligned and contains the components ship, tiger and stuka; And the other one is right aligned and contains end-button and exit-button. In other words, it means something like the following pseudo-HTML:


<hbox width="100%">
 <hbox align="left"> ship tiger stuka </hbox>
 <hbox align="right"> end-button exit-button </hbox>
</hbox>

Box nesting does not work yet, but alignment does. Automatic layout management actually appears to be quite easy to implement, at least if all you want is something HTML-like. You just make two passes over the tree–first, a bottom-up pass that calculates the size of all components, and then a top-down sweep that positions them.

After writing some code for arranging components horizontally I asked a friend of mine who is very proficient in functional languages if he knew a general way of expressing the iteration that could replace the ad-hoc code I had written. He came up with this neat piece of code and its brilliant name:

;; Return a list of results from applications of ‘termfun’ to the
;; elements of ’sequence’ and a carry.
;; ‘carryfn’ is used to calculate the next carry from the previous one
;; and the current element of the sequence.

(define (map/carry termfn carryfn carry sequence)
  (if (null? sequence)
    ’()
    (cons (termfn (car sequence) carry)
      (map/carry termfn carryfn
        (carryfn (car sequence) carry)
        (cdr sequence)))))

Using map/carry I could express a function for horizontal distribution of components without using any explicit iteration. Beautiful! Thanks, Tord. I considered many names for a similar iteration construct that remembered earlier results, but none of them was as succinct as “map/carry”.


Larger Maps Supported

February 1, 2009

I did a lot of work on the game yesterday, but I don’t have a screenshot to show this time.

I now use Cairo in a more sensible way so that its slowness does not show as much. Now it is also possible to drag the map around, by moving the mouse while holding down the left button. These changes together make it possible to use larger maps.

Another improvement is that I got rid of multithreading. Before, the Scheme runtime and the C++ code used two different threads. The reason for that was that I need to react both to events from the GUI and to Scheme commands sent via Stdin. However, this opened me up to the possibility of race conditions (the Scheme code could edit the scene graph while the C++ code was reading it), so rather than mess around with locking I decided to use just one thread and give the Scheme code a chance to run when the event loop of the window is idle instead. Actually, I think I will rewrite that so that the Scheme world is only called when there is stuff available on Stdin or a reaction to a user action is needed. Now control jumps back and forth between C++ and Scheme all the time for no good reason.


Aircraft and Unit Stacking

January 24, 2009

I have been working on adding aircraft units to the game today. Adding airplanes is more work than for other unit types, because aircraft units can be placed on top of other units. That means I have to write code for arranging stacked units in a way that is both pleasing to the eye and lets players refer to individual units within a hexagon unambiguously.

screenshot-090124

I am not done yet, but it seems to work pretty well now. The screenshot shows German divebombers stacked on top of other units. One of the units is always minimized when two units share the same hex. The unit that is not minimized is the unit that a click on that hex will refer to.

Right now, you cannot select a minimized unit without moving the other unit in that hex somewhere else first, but I plan to make it possible to select the minimized unit simpy by clicking on it. Now mouse clicks are interpreted as referring to hexagons and not to individual units, which worked as long as there was never more than one unit in any hex.

Work left:

  • Bombers can not attack other units yet.
  • Make it possible to refer to minimized units
  • Remove any overlap between units

Battleships

January 10, 2009

Today I completed support for another unit type–now there are battleships too!

An obvious difference between tanks and ships is the type of hexes they can move to, but another difference is that ships can fire at enemies farther away. So now all units have a range field that controls how far they can shoot. The ship in the middle of the screenshot has a range of two, which makes it able to attack the tank to the right of it.

screenshot-0901101

I have done a lot of refactoring in the Scheme part of the code lately. I’m turning more and more towards an object-oriented style because it fits many of the problems in the game like a glove, but I still use a functional style where it is appropriate.

There are still some problems left. For instance, if a ship attacks a tank two hexes away, the tank is able to return the fire and damage the ship even though it is out of the tank’s range. The tank can not initiate a fight with the ship, but it can defend itself at any range.

Next, I want to add some visual indication of which enemies a unit can attack. For instance, a cross hair could appear around an attackable unit when the user moves the mouse pointer over it.


Terrain-Sensitive Movement

January 4, 2009

I had planned to work more on the game during the Christmas holidays, but I did not start until a few days ago. But I made some clear progress these last few days.

The algorithm that calculates the set of hexagons a unit can reach now takes terrain into account. For instance, crossing a forested hexagon costs more movement points than passing through a hexagon representing farm land.

The screenshot shows the hexagons the blueish tank near the bottom-left corner can move to. The forest hexes at the top were previously reachable.

screenshot-0901041

At first, I thought all I had to do was associate costs with every edge and sum them up as I traversed the graph, but after a while I realized that breadth-first search (which is what I used before) cannot be used  with weighted graphs to solve this problem (unless all edges have the same weight). So I had to throw away the old search code and implement Dijkstra’s algorithm instead. Took me longer than I expected, but now the code is cleaner and handles weighted graphs properly.

I also simplified the rules for how close to an enemy a unit is allowed to move without having to stop. The new rule is simply that you cannot pass through a hex that is adjacent to an enemy unit. That is all that is needed, really. Thanks Peter E. for making a comment that made me realize how pointless the (relative) complexity of the old method was!


A New Breed of Programmer

November 30, 2008

Technological breakthroughs can enable new groups of people to compete successfully. For instance, the introduction of machinery in the industrial revolution did a lot to put women on equal footing with men, by reducing the advantage of physical strength. Something similar is happening in programming right now.

Patience, carefulness, and the ability to remember many facts and details were probably essential traits for successful programmers back in the early days of computers. Mistakes cost a lot of time when you don’t have a computer of your own and have to wait for the result until the next day.

After the arrival of the minis and personal computers, every programmer could have his own machine. This made a new style of programming possible, with rapid feedback and continuous experimentation as critical ingredients. Using Lisp you could even alter your programs as they were running. Getting everything right on the first try became less important under the new circumstances, and so the set of personality traits needed to be successful shifted.

The backlash against AI took Lisp and similar languages down with it, and in the mid-nineties almost everyone was using languages that had retained the edit-compile-link-run cycle. At the same time, code bases were growing larger and once again programmers found their workflows interrupted by long periods of waiting; This time not for access to a terminal, but for the compiler and linker to finish.

The arrival of Java and the Web turned the tide again–Java by moving Lisp concepts such as garbage collection back into the mainstream, and the Web by alleviating the need to memorize facts. Once again, the advantages meticulous and detail-oriented programmers had over their peers were reduced.

I think the circumstances have changed so much that the best programmers today are a whole different breed from the elite of the early days. The benefit of being able to keep lots of details in mind is much smaller now that you can find almost anything with Google in just a few seconds, and with new languages and tools that let you try many different approaches rapidly. In fact, I think some of the traits that once defined super programmers may even become liabilities. If you can find detailed information about anything instantly just by knowing the right keywords to search for, then trying to remember everything yourself is wasted effort. Just like a lossy compression algorithm can achieve higher compression rates than lossless ones, a less detail-oriented person has greater free capacity for learning abstract concepts than those who attempt to remember everything.