O'Reilly Network: How has the isometric, third-person
view you implemented for NetHack been generally received by players and,
particularly, NetHack enthusiasts?

Jaakko Peltonen: I believe it has been received rather
well. I've received hundreds of emails regarding Falcon's Eye. Several
people have said they started or restarted playing NetHack after finding
Falcon's Eye. Many new players seem to use Falcon's Eye.

NetHack enthusiasts have varied responses. One issue has been
visibility -- people liked to see the entire level of the dungeon at once,
while Falcon's Eye shows a scroll-able smaller area. I've tried to improve
this by including a radar-like mini-map, a separate top-down map window,
and high resolution support.

ORN: What are the graphics engine implementation
details for such a project?

JP: In NetHack each dungeon level is a 2D plane, so
full 3D isn't that useful for its gameplay. If the levels had elevation
differences (rising and falling corridors/rooms) that affected combat,
rolling boulders or the like, a 3D engine might be more useful.

At one point, I thought about making an interface with 3D models of
each tile, a full 3D version of Falcon's Eye in a sense. This would be
rather easy programming-wise, since only the actual tile drawing would
change -- most other graphics and background logic would be the same. I
intended to add artificial elevation differences, just to make the levels
look more interesting. I decided against the 3D version, since I felt it
would make the game confusing; tile-based movement and keyboard
compatibility might suffer.

One advantage of full 3D models is easy animation: each animation frame
is just a set of object-vertex positions. In most 2D games, frames are
separate pictures, which takes more memory and disk space.

Falcon's Eye doesn't currently have animation, but lots of people have
asked for it. I might add "static" animation like flickering torches,
running fountains, creatures glancing around, etc. "Dynamic" animation
like walking is more difficult for a number of reasons. First, to work
well, it needs separate animations for each movement direction. Second,
the interface then needs to find out what happened between turns. NetHack
doesn't provide this by default. Neither is impossible to solve, but they
do require more background logic for the interface.

ORN: It sounds like you created wrapper functions
around DirectX and SDL. Since SDL
itself on Windows is a thin wrapper around DirectX, is this the case?

JP: Falcon's Eye uses DirectX straight from the
wrapper on Windows. SDL is only used for the Linux and BeOS ports. This
avoids having a "wrapper of a wrapper."

Having a self-made wrapper -- instead of, for example, using SDL
throughout -- is useful since Falcon's Eye can then also support platforms
that SDL does not, like DOS. When the underlying API (such as DirectX or
SDL) is well-designed, the wrapper doesn't need to do much -- at best it
simply passes on its parameters -- so it doesn't slow down the game with
much overhead. Also, if a future version of DirectX or SDL were to change
the API to improve hardware support, I could simply change the contents of
the self-made wrapper functions to match.

ORN: What are your experiences with cross-platform
development with SDL?

JP: I found SDL quite easy to use. Its API is fairly
similar to the wrappers I had written myself. So in many areas, it felt
familiar to me already. The only feature I missed at first was MIDI music
support. I solved that by using an external music player the user can
configure. This turned out to be a good thing, since I could add support
for other music file types in the same way.

Since I had already used similar APIs, I didn't perhaps learn as much
as when I started GUI development earlier. I didn't look at SDL's
implementation details behind the API. I'm sure I'd have much to learn
there.

ORN: Any lessons learned from NetHack's portability?
Its separation of display from game logic?

JP: That was certainly a major help here. Both the
separation and the modularity were useful. NetHack only has a few files
for the display functions of each interface, and its internal data
representation is generally display-independent.

NetHack's portability across different computer systems -- UNIX, DOS,
Linux, Windows, Amiga, Mac, different processor types, and so on -- is
quite incredible. It goes beyond the display alone and includes
considerations for things like file handling and compiler
specifics. Although I don't intend to support Falcon's Eye across as wide
a range of platforms, it does help me understand which kinds of
platform-specific features and programming solutions to avoid.

ORN: What advice would you give to someone writing a
GUI for a well-loved character-based application? (One can imagine the
complexity of implementing gVim, for
example.)

JP: One should first consider the goals of the GUI. In
most cases, a GUI can provide more clarity or quicker ways to accomplish
tasks. If the character-based application has clear problems with either
of these, that's something the GUI should try to improve.

There are several routes for improving clarity. For example, character
applications are usually oriented for a rather small display with few rows
and columns. By contrast, many though not all GUI applications can assume
there is a moderate amount of screen area available. Restructuring the
display for more space can make it clearer. The GUI graphics also affect
this; they can help associate related components, but too many graphical
effects can make GUIs look cluttered.

Character applications are naturally restricted to character symbols,
so they may need to draw complex structures (arrows, boxes, diagrams,
buttons) with characters. A GUI can draw these in a more intuitive
way. Also, GUI applications can use color or other highlighting where
character applications need separate messages, capitals, etc., and can
provide more feedback by tooltips, sub-windows or other means.

Regarding speed, in a highly evolved character application, the
keyboard usage is probably already well optimized. Simply adding buttons
for key presses won't make much difference. Instead, one should consider
how the mouse can best be used in tandem with the keyboard. For example,
character applications often have an "active area" for user input, with a
command line or text menu, and the rest of the screen is for information
only. This can make the active area feel cramped. In a GUI, the entire
application area can accept user input.

Overall, the GUI should work in concert with the keyboard interface.
Especially with widely used programs, users have learned how to use the
character interface quickly, and changing this functionality probably
hurts the overall speed and adds an unnecessary learning step. The GUI
should instead provide alternatives. Some users may eventually use a
combination midway between the old and new interfaces. Allowing this can
sometimes mean making several different ways to do a task, which takes
considerable work in both design and implementation, but I believe it is
well worth the trouble.

ORN: How does having artistic skills, such as you
clearly have, both help and complicate things when developing graphics and
sound programs?

JP: One advantage is that I always consider both the
presentation and its implementation together. I know what kinds of
graphics and sound I can create, as well as how to solve some programming
tasks. I can then design programs to get the best combined effect from
these areas.

I often start out designing an interface simply by creating a mock-up
image of how it should look. On the basis of the image, I can judge how
the program logic should be arranged. What is the function hierarchy,
which structures are fixed and which need to be modifiable, how does the
program flow through the task? When the basic layout is fixed, I finalize
the look of each component, often simultaneously with the code that uses
it, which helps with testing.

If I started with code alone, I might stress "elegant" coding
solutions, which can sometimes be cumbersome in practice: too simple
hierarchies can lead to overly complex data representation and vice
versa. Looking at the graphics gives me a user's perspective, which helps
find the necessary programming compromises. On the other hand, knowing
implementation details helps keep in mind what ideas are easy to realize,
so that I don't draw interfaces too difficult to program.

This kind of development can sometimes mean I need to draw the
interface graphics several times over if I do change the program
structure. Also, sometimes I can spend too much time over graphics when I
should concentrate on programming, design or sound; if one area lags
behind others, I might not be able to effectively test them together.

Overall, though, I think there are more positive than negative effects
from knowing these areas. It can also help with long development periods
-- if I temporarily grow tired of drawing or sound design, I can switch to
programming, and back again later.