21 December 2015

Treasure

As I mentioned in the last post, I am trying to make as much of the game data-driven as possible. Treasures are a good case in point.

King of Dragon Pass has 133 treasures in the latest version. The exact number matters for saved games (in other words, adding treasures changes the file format). Each treasure has specific code somewhere in the code to implement it — sometimes more than once, to handle battle treasures, source, or reference. This is of course a lot of code to write and test, and it makes it difficult to add treasures. We can do better.

Six Ages has the advantage of being the second time we’ve done this. The treasures are fairly similar in behavior to KoDP, with effects like

.mood+=3 on any Hunting win
+1 on tests vs Skepticism
characters gain +1 on Magic and Diplomacy tests where the player chose them as testee
increase q by 1 on any win vs. Duel
heal d4 sickened each Earth Season

The first four are patterns that are repeat frequently (with different skills or oppositions). The fifth is unique, but is best handled by a script that runs each Earth Season checking for the specific treasure (rather than KoDP’s approach of putting this in C++).

Here's how the first two can be specified:

{key = 1037, name = "Happy Hunting Ground",
summary = "Dirt that improves mood when hunting goes well",
onWin = {"Hunting", "mood", 3},
pool = TRADE},

{key = 1041, name = "Golden Drinking Cup",
summary = "Helps overcome skeptical minds",
modifiers = { Skepticism = 1 },
pool = EXPLORATION},

Obviously there needs to be code that checks for the onWin slot when a test is won, and the modifiers slot when a test is made. But that code then handles a wide variety of treasures.

Treasures now have unique keys, so it’s easy to add new ones. And the pool slot makes it simple to specify that a player might obtain the treasure by trading with another clan, or by exploring.

Combined with scene tagging, it’s also much easier to implement a treasure like KoDP’s Iron Spike, which included the effect

gain +1 to all tests made during Scenes R137, R163, R166, R181 and R200

If this treasure were in Six Ages, the effect would be specified

modifiers = {["@troll"] = 1 },

which means it would work for any new troll scenes, not just those created at the time the treasure was created.

Of course, nothing about this approach precludes custom code. But it massively reduces it, so only unusual treasures will need it.

10 September 2015

Data Based

I’m trying to make Six Ages easier to create and (hopefully) expand, compared to King of Dragon Pass. One way developers do this is to turn code into data. This can make it much easier to add new content without cracking open the code.

I was about to implement exploration at home, which presented a good opportunity to do this. In King of Dragon Pass when you explore without moving the exploration marker, this code determines what can happen. If we add a new possibility (or have to remove one), the code has to change in several places.

In Six Ages, this is reduced to four lines of code (which actually handles the default case which is not shown for King of Dragon Pass), and this data. New items can be added (or removed) trivially, which is good because I have not yet written all of the new scripts.

Note that the code specific to exotic goods doesn’t exist any longer either. Similar lines are now in scripts, which is a similar push to move code into scripts. (Scripts are still code, but a much more limited form, and much more specific to the game.)

Exploration in arbitrary places also uses data, though it’s a little more complex (and integrated with the map metadata).

While the data-driven approach is easier, it’s worth noting that there can still be bugs caused by data. In this case, listing a script that doesn’t exist would be bad, and there’s no easy way to catch that, since this list is in a Lua file, and the script is in an OSL file. However, it’s easy enough to write a unit test.

08 August 2015

Six Ages After One Year

I began working full-time on Six Ages a year ago, when Shenandoah Studio had to shut down its Philadelphia studio. Although a year is a long time for many indie games, Six Ages is large and ambitious, so I certainly didn’t expect to be done yet. But how’s it going?

We began with infrastructure work. Like King of Dragon Pass, Six Ages is set in the mythic world of Glorantha. Robin Laws and I developed the specific elements of the setting (consulting with Jeff Richard and Greg Stafford). And I got a team of concept artists to sketch what it would look like. Jan Pospíšil has continued to add sketches.

I wanted to continue using OSL, since it works well for the sort of interactive scenes that Six Ages will use. But I wanted to make it a lot more flexible, so it would be easier to update the game (or even do another some day!). The implementation of OSL used in King of Dragon Pass is very specific to particular versions of the game. So I came up with a better approach, which meant reworking the scene compiler as well as the runtime. This enabled a way to test all the scenes, which in itself means it was worth the investment.

Robin and I also discussed what elements of game play would be the same and what would change, both to support the story and to make it easier for players (and designers) to understand. For example, we wanted to make certain warnings easier to spot, without having to check advice or be faced with an alert. And we wanted to make it easier to tune the impact of leaders on executing player decisions.

Once we knew this, it let Pat Ward (who I’d worked with at Shenandoah) and I come up with a user interface design for the game. One goal was to better support multiple screen sizes (which can be tricky in a game). I have implemented much of Pat’s design, but haven’t polished it at all. My goal was to make all the screens work, but not spend a lot of effort making them right until we’re sure the game works.

Also on the art side, I got to work with one of Moon Design’s artists to make a great new map.

Meanwhile, Robin was writing scenes. With me doing infrastructure and design, there was a huge backlog of scenes that were written but not in the game. I got Jeff Dougherty (who I’d worked with at Shenandoah) to help code them into OSL. And once enough of those were in, Liana Kerr began exhaustively testing them.

Right now, there are 266 scenes written. 161 have been coded, and proved to run. 23 have had all branches tested. There are definitely enough scenes in to start giving a feel for the game. As Robin said on our Slack,
It has enough scenes now to give it that great addictive, potato chip quality of KoDP.  "I'll just do one more and then stop... okay, one more... what, it's Sacred Time again already?"
However, right now I would say the game is runnable but not playable. You can certainly get a taste, but can’t really perform all the actions you would do in a game year.

It turned out the original concept art wasn’t quite detailed enough for the player’s clan, so we have continued to work on that. It’s finally to the point where we can produce illustrations for the game.

But this is a screen shot.
So one year in, we’ve made a lot of progress. The game is still a long way from being done, so it is definitely early to talk about a release date. Which also means it’s too early to talk more about any game play specifics.

But we have a game that can run scenes and save state. It handles multiple screen sizes. It has most of the underlying economic model hooked up, including magic. It has some great art. There’s still a lot of production to go, and tuning and testing of game play (as opposed to specific scenes) has not started. But I think we’re on track to make a cool game.

20 July 2015

Script Testing

Looking back to the original King of Dragon Pass scene compiler, there’s a comment (probably written by Shawn Steele) that reads
ToDo:
Different program: Batch test all of the scenes, follow all of the conditional paths, etc., to make sure that things are as we would expect.  This would go a long ways to making sure that the scenes are coded properly.
We never wrote that program, and with modern unit test frameworks it doesn’t need to be a separate program. But for Six Ages, I did want to test every script, at least for gross errors (they still need human testing). I’d written unit tests to make sure that a single script could run, but running every script is quite different.

First, I redefined the problem slightly. Rather than following all conditional paths, I just wanted to run every response of every scene. (Conditionals depend not only on dice rolls, but also on things like having a feud, or having run the same scene before and having made a certain decision.) This turned out to be very useful to catch script functions that weren’t actually implemented yet. It’s much faster running the tests than going through a scene manually. Plus being automated, any issue was going to stay visible until fixed, instead of possibly falling through the cracks.

Except that’s not strictly true, due to what I call “lucky dice.” There were scenes that would sometimes work and sometimes fail. Usually this was due to having a specific person on the clan ring. One answer to this would be to make dice non-random. They could generate the same sequence of numbers every time through. I chose not to do this for a couple reasons. First, it would be even further from the "all of the conditional paths” idea, since it would be the same path every time. In other words, it focused on making the tests work, and not making the game work. Second, due to the nature of what was being tested, it didn’t really guarantee repeatability. The dice rolls would be the same, but their contexts would be different as we added scenes or revised them. (In other words, the 57th roll might always be a 16, but that roll might determine a clan attack in one run, and random text in the next after we fixed a bug.)

Another factor is that running every scene is unnatural. Most scenes have some sort of condition (there is no point in having someone ask for a treasure if you have no treasure), or are explicitly designed to follow another scene. The unit tests didn’t test for this sort of continuity, but forcing a scene to run when its precondition wasn’t met often caused problems that would never show up in a real game.

For a while, I just lived with the false positives (a scene failing if there no friendly neighbors, or after your advisors died in an apocalypse) that came and went. We’re not using build automation, so it was annoying but not really gumming up the works.

It seemed like a more serious limitation that the test would run every response, but couldn’t handle other interactivity, like picking a clan to petition, the number of warriors to hunt down a monster with, or how large a gift to offer. OSL is designed to pause execution and wait for user response, then resume running the script. This is all implicit — the interpreter doesn’t literally sit there waiting (which would be a great way to run down your batteries), it sends a message and quits. It took me a while to figure out how to hook into this asynchronous process in a way that would work with unit tests (which are essentially synchronous, running a script until it is complete). Once I did, the tests suddenly got a lot more thorough. (A typical response might ask you for a clan, a diplomat, and a gift, all before resolving the negotiation. So a typical response had only been very partially tested before.) And this meant that there were more false positives, since there was more code being run, but depending on a particular story context.

I tried to ensure a proper context (when testing, hard-code a friendly neighbor), but false positives would still come and go depending on chance. I finally came up with an approach that allowed me to get broader coverage by having free-rolling dice, but also avoid testing scenes in a way that was almost guaranteed to fail.

The goal of this test was to exercise each scene as fully as practical. Randomness helped give broader test coverage within a scene (at least over multiple test runs). But randomness cascading through the test run was causing problems. Ergo, I needed to eliminate the cascade. The breakthrough here was to save the game at the beginning of the test, and restore before running each response. This minimized randomness in a scene’s context, so it would never be run in a known impossible situation.

The final step was to capture the clean setup in a script, which is run at the start of the unit test (before the game is saved).

So once again, we can run the test when coding up a scene, and the errors it reports represent real problems.

We’re still not going through every part of a script — the player decision maker doesn’t handle combat. (It also gets stuck in certain negotiations by refusing to up its offer.) And while saving and loading is fairly fast, doing so for multiple responses for over a hundred scenes does add up. But exercising every script still takes only 32 seconds on my development machine, and running all the unit tests is a single command, so it’s not really a big deal.

Everything this test catches would eventually be found by QA, but only much later. It’s always better to shorten the time between creating a bug and finding it, so things are still fresh in the coder’s mind. And test automation means QA can spend more time on bugs that only a human can catch. So it’s now part of our scene coding process.

13 July 2015

Unit Testing

One of the deep secrets of King of Dragon Pass is that we shipped a buggy program in 1999. No, not the normal sort of low priority issues, or bugs rare enough you didn’t find them in QA or beta testing. KoDP relies on its scripting language to execute interactive scenes, and there is a serious bug in the OSL interpreter.

Luckily, there’s a workaround: the logging we put in to help debug OSL masked the bug. So instead of shipping the “release version,” we shipped the “debug version.” (This sort of issue is not unique to KoDP, by the way.)

This was actually something I forgot when I converted the game to iOS. (Looking back at my notes, I may have rediscovered this a day after releasing for iOS…) And I ended up making the same decision. It works in debug, so ship debug.

It turned out that even with debugging output turned on, there were a few extremely rare situations where the bug would surface. I believe I found and fixed some of those, but with tools, interpreter, and save files all revolving around the original implementation of lists, it was hard to make enough changes to be certain. And this was tricky code.

Back in 1997, we were very concerned about size (on disk and in memory) so we went to a lot of trouble to make lists (of clans, people, tribes) very compact. In retrospect, we committed one of the cardinal sins of programming: premature optimization. It was a noble goal, but at the start of the Six Ages implementation, I looked at KoDP saved games. Out of 1549 saved variables, 8 were lists. So compact storage was completely unnecessary. Lists are used far more frequently than they’re saved (for example, in picking a random clan from a list of neighbors who don’t hate you), so correct behavior was really the key.

While I didn’t really want to rewrite part of the game that was basically working, there was no guarantee that it would continue to (mostly) work with a whole new game. So Six Ages has a new implementation of the scripting language, from the bottom up. This supports new features, but is also an attempt to get it to work correctly in all situations.

So how do you guarantee correct behavior in a complex program? At one level, you can’t — or if you could, it would take too long to prove. But you can write code to test your code. The new implementation of OSL needed unit tests. (The original game had none — it would have been very unusual in the late 1990s.)

Various testing methodologies are big in business software (often combined with build automation), and a sign of a quality open source project is having tests. But it can be tricky to test games. There are ways to deal with randomness, but specifying a situation (like having exactly one non-hating neighbor, the right mix of advisors, or a raid history) or expected behavior for a multi-stage interactive scene can be tricky. And a lot of a game is its user interface, which poses its own testing challenges. Fortunately, while a game as a whole can be difficult to test, subsystems can be tested. The scripting language is just such a system. And even better, the handling of lists requires no testing tricks.

All tests pass!
While I didn’t really use test-driven development, I did start writing unit tests very early, and once in a while did write the test first (specifying correct behavior) and then the code. And when I find a bug in the low-level code, I’ll add a test to make sure the bug is actually fixed, and not reintroduced by later changes. Looking back at the development diary, I see comments like
  • Working on iteration. Hooray for unit tests.
  • And glad I made a unit test, it looks like I need to add a copy of the treasure if I’m mutating them
  • Again, hooray for unit tests. Did it for children, since that’s a kind of complex thing. And it caught a problem with setGoods: too.
  • Oops, that type broke stuff. Hooray for unit tests!
Next post, even more automated testing. (The previous post discussed some of the design changes in OSL.)

06 July 2015

Scripting Changes

King of Dragon Pass’s interactive scenes are the core of the game, and at their heart is the Opal Scripting Language (OSL). Since Six Ages will follow in the tradition of KoDP, it too will rely on OSL.

Or would it? OSL has some limitations, and I considered switching to Lua, which is a much more powerful scripting language (and widely used in games). If I was going to have to rework OSL (see below), why not just move to a well-known and reliable language? In the end, I decided to stick with OSL. Its syntax was designed around the needs of KoDP-style scenes, which makes it easier to convert from an author’s script to a runnable script. And OSL scripts can be saved saved in a single file but loaded individually, which didn’t fit the Lua model. (This is likely to be important on memory-constrained mobile devices.) Finally, I already had an OSL compiler and interpreter.

They just needed updating. One of the biggest problems was that the number of scripts and variables had to be known when a game was saved. This made adding new content difficult. This meant some significant changes under the hood to allow for future growth.

I also wanted to make scripting easier to use. It was already safe (in that problems with a script were very unlikely to crash the game), but you sometimes needed to jump through hoops to work within the syntax or implementation details (you could only get the properties of some variables, not all). Placeholders could be easier: <duel/fight> rather than <d2:duel/fight>. And could allow nesting: <it was not {t}’s fault/{t} was blameless>. Or even allow music to change in the middle of a scene.

Another usability improvement would be to allow scripts to run other scripts, or to check the scene queue.

A few small changes would allow the clan questionnaire to be a script, rather than custom-coded. And we could tag scenes, for example to make sure they appeared at random at the right dramatic phase.
scene: scene_1Friendmaking
scene001, left, [CouldBefriend <> 0], @Diplomacy, @actOne, @staple, mayRepeat
music: "CouldBeGood"
[SceneUsed(scene_1Friendmaking)] {
  f = false
} else {
  # Never been used, so this must be the start of the game
  f = true
}
And there was another reason to rework OSL, which I’ll get into next time.

05 May 2015

Map Making

As you recall, I had no idea how to make the King of Dragon Pass map. This is not quite as dire as it sounds, since it wouldn’t really make sense to use Windows BMP data for the zones (which is my guess as to how things used to work).

(Quick recap: the actual map is a set of irregularly shaped zones. For purposes of exploration, there’s a hexagonal grid. The map you see in play is the combination of these. But the part I have to create for a new game is the zone data.)

I figured that the basic metadata was easy enough to code by hand as Lua data, like this:

["Stones"] = {flags = kFeature},

The hard part would be the (geo)graphic data. I dug out my old Wacom tablet (so old that itscustom drivers can’t be used under the current Mac OS X) and started drawing zones. Each zone was a separate layer. I couldn’t figure out how to easily export these in Acorn (which on the other hand looks like it has a great workflow for making button slices), so I used Photoshop. Unfortunately, I couldn’t use my old version, and had to get the latest “cloud” version to export transparent PNG files for each layer. For the next step, each exported PNG is the same size as the full map (most of the pixels are transparent).

I figured I could feed these to TexturePacker, and at the very least, get a file with the coordinates of each. Although I’m not using Corona, I tried using that as the export format, since it’s Lua-based. Sure enough, I got a Lua file with lines like

["Stones"] = 72,

{
  -- Stones
  x=1824,
  y=301,
  width=111,
  height=48,
  sourceX = 873,
  sourceY = 678,
  sourceWidth = 1500,
  sourceHeight = 1375
},

as well as a sprite sheet (which has the non-transparent parts of all the layers).

I can easily read the two Lua files to get game-specific metadata and the image-specific data.


Stones.png 
Although KoDP’s zone data included the bitmap, I’m just leaving that in the PNG files. (It turns out that for speed, I re-export them trimmed.)

With the zone data available, hit-testing is a simple matter of a quick check for zones whose bounding box includes a point.  If a zone passes, I need to load the PNG and see if the pixel is opaque or not.

Once hit-testing was in, I could finish the metadata. This was the tedious part of noting which zones were adjacent to other zones (which is used to figure out which clans are neighbors). I’ve worked on games where specialized tools analyze the data, but figured it wasn’t worth the effort for this particular map. It was worth the effort to visualize the data with an interactive debugging mode. Here, the zone NBE is selected, and its neighbors marked.

["NBE4"] = {neighbors = {"NBE2", "NBE3", "NBE5", "NBE10"}},

The entire process mostly concentrates on the data (drawing the zones and establishing connections). And it has an advantage over the KoDP approach in that everything is human readable.

15 April 2015

Dissecting the King of Dragon Pass Map

The approach we used for King of Dragon Pass’s map worked pretty well, so I expect to be using it again. If only I knew what it was…

That is, I know how the King of Dragon Pass map works, but not how to make it.

The map tracked where clans were, and what you had explored. Exploration was represented by a hexagonal grid. (Coincidentally, the hexes are the same size as the Dragon Pass board game map, or Guide to Glorantha. They’re positioned for game convenience though, and don’t try to align with any published map’s hexes.) A hex was considered explored or not. The map was drawn by first drawing the unexplored map (the memory of your ancestor’s time in Dragon Pass). Then the detailed map, masked to show only the explored hexes, is drawn on top. Finally, any labels (such as clan or tribe names) are drawn.

KoDP clan zones labelled in this zoomed-in view
Clans were positioned in one or more zones, irregular shapes that conform to the topography. At the start of the game, clans occupy contiguous zones, though occasionally this can change during play. Zone assignments weren’t completely fixed, though for example the Colymar tribe’s clans started out in one of the nine zones of the Nymie Vale. Note that there are spare zones at the northeast of the map, intended for clans that enter the game during play.

There are also zones used for exploration, so any expedition to say Snakepipe Hollow can result in the appropriate scene or news.

As data structures, zones consist of some metadata (name, whether the zone is along a river), a list of neighboring zones, positioning info, and a Windows Bitmap object defining the shape. This is all saved in a map file. Although the iOS version improved how zones are shaded, the basic data is exactly the same as the CD version we shipped in 1999.

Partly that’s because I have no idea how we made the data file! I still have a bunch of old tools (like a scene decompiler, which was used early in testing and abandoned), but nothing that creates the map. I know that Shawn Steele wrote the tool, but I don’t know how each zone was defined. Presumably there were .bmp files for each of the 122 zones, but I really don’t know for sure.

I’m currently in the middle of working on the new map, so I reviewed all the existing code (and added a quick way to visualize zones, as seen above). This post summarizes the starting point. Once the new system is done, I’ll describe what changed.

02 April 2015

Scripting

Six Ages uses the same Opal Scripting Language (OSL) that we used in King of Dragon Pass (although it’s been improved — a topic for future posts). This is a domain-specific language that’s intended to make it easy to get interactive scenes into the game. As a scripting language, it can also make it easy for someone who is not a C programmer to code game logic.

As a trivial example, here’s a response from one of the new scenes. Getting scenes from the writer to the game is not always this simple, but quite often is. OSL makes it much easier than other scripting langages (like Lua or JavaScript) to handle basic game elements like responses, saga, and text output. Its syntax is designed for the game.

Response 4: Decline.
{
saga: We declined.
sagaText: They said there were no hard feelings and went on their way.
}

One of the goals for Six Ages is to make more use of script, as opposed to custom code. King of Dragon Pass had a lot of game-specific logic in its C++ code. This basically baked in a lot of assumptions, meaning that code couldn’t easily be used in Six Ages, let alone a possible sequel or another game entirely.

The clan questionnaire in King of Dragon Pass was at least driven by data, but had its own code to show the questions, and to provide a recap of the answers. Six Ages has a similar questionnaire, but it’s a series of scripts (which allows for a lot more flexibility). The final page recaps your answers. When you start the game, KoDP ran C++ code that looked at each answer and wrote to the saga, to summarize your answers. But, we already have a script that summarizes answers — the recap page. So a slight variant of that writes the saga. No special code!

In KoDP, we seeded certain scenes (such as the first encounter with the ducks) from C++. In Six Ages, similar scenes are now seeded from the script that runs at the start of a game.

#seed this scene early; equivalent of Bull in KoDP. Season NOT Storm NOT Darkness
x = d3
[x = 1] t = NextSeaSeason
[x = 2] t = NextFireSeason
[x = 3] t = NextEarthSeason
trigger scene_6 t + 5 * d2 # Year 2 or 3

OSL is intended for this sort of thing, so this is much more compact and readable than the non-script equivalent.

In KoDP, there was special code that let you know about the Horse Spawn. Now, a similar situation is handled by the script that handles battle.

Robin Laws wanted a few standard calculations to occur in each scene. So there is now a special script that runs before any scene, that makes a number of political calculations (both external and internal).

One new script facility is intended to leverage scripts: variable watching. You can write a line like

StartWatching("debut")

and any time the variable debut changes, a script will be called (by convention, the variable newValue has the new value of the watched variable):

code: fragment_debutWillChange
[newValue = true AND debut = false] trigger news_ItHasBegin 0

This is also an advantage of creating your own language: if you need a special feature, it’s easy to add. (The disadvantage is that if you need a feature that’s in a more common scripting language, you have to add it.)

22 February 2015

Tools

The team is using a variety of software to make the game. Some of it’s pretty obvious (i.e. Photoshop for art), but some of the tools are worth noting.

Planning with Opal
A lot of my note-taking and planning happens in an Opal outline. Opal is a great lightweight tool for making lists, putting them in hierarchies, rearranging them, and searching. It only runs on Mac OS X, but I am at my desk most of the time, which makes it a great way to keep a development diary. I use it to track ideas, but I’ve also created outlines of documents I’ve fleshed out in a word processor. And, I used it to plan the Tools Week tweets and this post. I am a little biased towards Opal because I wrote it, but others like it too. You can download a 30-day free trial.

Searching in Slack
The team is distributed, so we use Slack to communicate. Loosely, it’s a team-oriented chat system. There are similar products, but it has the best user interface, and very reasonable pricing. (We’re still able to use it at the free level, though I expect to upgrade at some point. So check it out via the affiliate link…) I have been unhappy with chat-based work in the past, but Slack has decent organization (although it still lacks threaded messages) and searches not only messages but files you post. Team-related email has dropped to about zero, which is probably a good thing. While I am still trying to figure out the best way to be transparent and encourage collaboration without swamping people with notifications, it seems to help create a little bit of a true studio feel. (Some of this may be due to the size of the team — a Slack team for Philadelphia iOS developers seemed horribly noisy. Admittedly, they aren’t people I’m actively collaborating with.) It integrates with an number of external systems, though we don’t really make much use of that.

There are other file sharing/synchronizing (or should I just go with the flow and call it “cloud storage”) solutions, but we use Dropbox. It’s been out there a while and you probably know about it, but if not, sign up for a free account. (Use the affiliate link and we both get more storage.) We have had one or two issues with the fact that shared files can be accidentally deleted, but it’s been a good means of bulk sharing (both of folders of concept art ideas, and large files that are too big to email). Another handy use of Dropbox is getting user interface mockups onto an iPad or iPhone quickly. We also do primitive project tracking by moving files between “To Review” and “To Revise” folders.

Kaleidoscope’s image comparator
The files in question are Word documents with the scenes that Robin’s writing. I compare versions with Kaleidoscope, so I can make sure important revisions don’t slip through the cracks. Word does have a Track Changes mechanism, but I find it much easier to use the side-by-side comparison. It also compares many other file types, and has a clever interface for showing graphical differences. You can get a free 15-day trial as a direct download, or get the app through the Mac App Store.

Editorial lets me keep notes in Dropbox and sync them among all devices, for when I’m away from Opal (but have an iPad or iPhone with me). It happens to be a Markdown editor, but mostly I find it easier to have searchable, synchronized notes than using Apple’s Notes app. (I use TextEdit if I need to get at the files on my Mac.) Get it from the iOS App Store. (Federico Viticci has an extensive review.)

Spreadsheets are a staple of game design. I prefer Numbers (mostly on Mac but also iPad). Robin uses Excel. They’re great for freeform tables, simple budget and time planning, and sometimes even calculating things.

Although there are a number of reasons it works poorly for game development (e.g. assets can be very large or hard to merge), we’re using Git as our version control system. The size of the team and nature of the assets alleviate some of those issues. But one reason is that we can host on Kiln, and integrate changes into Fogbugz. Kiln is a decent Git host, though I really didn’t make a wide search. Mostly, Fogbugz is the best bug tracking system I’ve used, and it integrates very well with Kiln. (Just put "case 1234" in a checkin comment, and the changeset is linked to the bug and vice versa.) Fogbugz has a focus on user interflow and making it as simple as possible to capture bug reports (for example, you can email reports, which is great for in-game reporting). It’s also got some project management features. And for a small startup, Fogbugz and Kiln are free! (Again, we will probably need to upgrade at some point.)

09 January 2015

Concept Art Followup

Although the main brainstorming aspect of the game’s concept art is over, in one sense we only took a surface look at eight cultures. For example, so we could iterate quickly, I didn’t ask for color sketches. But color is something that’s obviously important for the look of the game, and Jan and I are discussing it now. (By the way, I highly recommend Blue: The History of a Color, although you probably need to track down a used copy or check it out of a library). And Jan is also trying to make sense of my “take the hat from this sketch, and the man’s shirt from this sketch (but change the length), and the woman’s pants from this one” instructions.

And the artists are asking questions about whether there would be jade, or if it’s too far from the ocean for a certain people to have shell beads. In one sense, it doesn’t matter — it’s a game, about a fictional world. But it’s the sort of attention to detail I think really matters. It’s important to fit into the Gloranthan canon, but it’s even more important to be portraying a a realistic and consistent setting. A player won’t know or care that a drawing of a woman with a pearl earring is “correct,” but the game is building up a story out of hundreds of pictures. If they each tell a different story, the overarching epic is not as strong. It’s great to be working with artists who care not only about how a single image should have a range of colors, but also how they are contributing to the overall story.
Art review at A Sharp

By the way, in the last post I forgot to include the picture of the review meeting Elise Bowditch and I had, with printouts spread all over. (In our informal meetings I would often bring up images on an iPad. Even though as a developer we have a number of iPads, we don’t have that many — the paperless office is still a vision for the future.)