Some thoughts on the new Dungeons & Dragons

That was once known as "D&D Next" has been released as Fifth Edition Dungeons & Dragons. Sorta. Mostly. We don't quite have the Monster Manual (Well. This has released since I started drafting this post) or the Dungeon Masters Guide yet but we have the Players Handbook, a Starter Set that has a streamlined rulebook and an introductory adventure, the first half of an Adventure Path (Hoard of the Dragon Queen), and free PDF "Basic Rules" files that let you build a small set of characters out to level 20. And there's been some restructuring to the organization so you don't really need the DMG to run a campaign. The DMG is supposed to be mainly a repository of optional rules "modules" and hacks to modify the game. I believe magic items are back in the DMG now, but if you run the Starter Set or Hoard of the Dragon Queen they list some magic items there, and there is an online supplement for the latter that lists the magic items you need there.

In fact this whole digital thing is an interesting departure for Wizards of the Coast. Although you'd only have a few class & race choices for PC's it's entirely possible to buy Hoard of the Dragon Queen, download the free Basic Rules and the online supplement and you have everything you need to run a campaign up through level 7. When they release the second book in the Tyranny of Dragons Adventure Path they plan on updating these files to cover that and you've got an entire campaign and you're only out $60 (retail cost, less if you shop Amazon or get a deal). And the rules are all compatible, so you can have one player using the PHB and really tweaking out his custom fighter while his party-mates just run the stock cleric and wizard from the Basic Rules.

This is a big departure from fourth edition where A ) WotC was releasing a new hardcover book every month and B ) the only online concession was the generally terrible software provided as "D&D Insider". Of course, time will tell what happens next year to the game, and there was a lot of talk a while back about how Hasbro was insisting D&D needed to achieve Magic-level sales or they would just shelve the brand. I saw an interview with Mike Mearls (lead designer of 5th edition) where he explained that the plan now was that a healthy D&D leads to video games, media tie-ins (books, movies, cartoons), and even toys and the like. He made a major point of saying once you have the core three books and the Adventure Path you have years of gaming and does putting out more rules enhance the game? Maybe it doesn't.

So all this babble is great background, but what do I think of fifth edition so far? I like it a lot. I've run two sessions from the Starter Set adventure, read through the Players Handbook and I'm reading Hoard of the Dragon Queen currently. My one sentence summary of the differences is this: Recent RPG's had become complex system of rules focused on letting GM's and players tell each other "No", whereas fifth focuses back on telling GM's and players to work together to tell entertaining stories. When I play many games the experience is this back and forth where rules and rules exceptions are stacked up and compared until an answer comes out. When a player asks "Can I jump over the bar and then run up to this bully and knock him over?" everybody wants the answer to be "Yes. Or at least you may certainly try". We don't have to first look up the rules for the DC of a bar jump, then figure out how much movement that should take up, then check to see if the character has any feats, class features, or magic items that modify the attack roll, then figure out what the bully's defense is (which can be impacted by feats, class features, or magic items) and then finally make the roll. Oh but wait, the bully hasn't gone yet so he's flat-footed which means all his defenses are different, and does this magic item work when the owner is flat-footed? You want rules that give you some quick and dirty ways for a GM to make a quick judgement call and move on.

I never used a battle mat with first or second edition D&D, or even GURPS. I skipped third edition when it came out, so fourth was my first exposure to a system that really requires a battle mat. In theory it should make things easier to see and allow for cool terrain effects and so on. In practice getting terrain effects perfectly balanced against player powers so they are neither over or under-powered is difficult and the battle grid ends up providing more "No's". "Well you can only move 30 feet and that guy is 35 feet away." "Those squares are difficult terrain so they cost more, and that's your second diagonal square so it costs double". "Oh but is the difficult terrain due to forest underbrush? At level 3 I took Forest Stride so I can ignore that difficult terrain" Uggh. Ask "Can I hit the guy?", get an answer and move on.

There have been a lot of posts around the web about what fifth brings to the table, so if you're interested you really already know. I love replacing a whole host of little modifiers with the concept of advantage or disadvantage. (Rogue protip: advantage gets you Sneak Attack. If your DM has given you an inspiration point for playing to your flaw or bond then you can spend that inspiration on any attack, which means you get the normal advantage AND Sneak Attack. We realized that in the last session I ran and it's super-powerful.) It makes things move so much faster at the table. I think the "spell slots" do a good job of balancing old-school Vancian magic with a bit more flexibility than wizards and clerics usually have in fantasy games. It also solves a weird problem where Magic Missile is always an awesome spell and at high level you don't have any other use for first level spell slots: you can cast Magic Missile as a fifth level spell or as a first level spell and the spell scales accordingly. I love the stripping out all of the crazy math treadmills where everyone gets a +1 to their attacks and then all of the monsters get a +1 to AC for a net no change and you reach these silly values attack rolls where you're rolling a d20 and adding 27 to that value.

Frameworks in Xcode 6

 

EDITED TO ADD 2014-11-10: The edit below was written while I was setting up Squarespace 6 and published to the Squarespace 5 version. I noticed that over the weekend so I went back and copied the change here.

EDITED TO ADD 2014-10-17: I found a pair of interrelated gotchas about frameworks on iOS. so there's some new information below. I did not originally have step 10 about copying the framework into the app bundle. That worked OK on the simulator but I got a dynamic link error on hardware without step 10. I also didn't have step 11 which addresses if your app target is pure Objective-C but your framework contains a Swift file. My first version of HJSKit.framework was all Objective-C code from Combat Imp but I added a Swift file while working on the new project and it broke the framework version of Combat Imp until I set the proper build flag.


Combat Imp is in the store and I have a new version winding through App Review, so I've started looking at a new project. I immediately wanted some of my custom code from what I call HJSKit and I decided it was time to convert from just using source files in multiple projects to having a shiny new framework. However that's more complicated than it ought to be. Frameworks are new to iOS 8 but there have been some weird ways to hack them for years, so it's difficult to search the web for information about the modern ways. There was a WWDC talk about frameworks this year but what they showed was creating a framework inside a single project for multiple targets to use. The Apple development documents are more for OS X and say things like "You don't want to make an umbrella framework" which is wrong: see the Swift/Obj-C interaction document which specifically tells you to use an umbrella framework. I wanted to have a completely separate project, complete with version control, and then I could add that framework to multiple projects. Oh and the new project is in Swift so I wanted Swift/Obj-C interoperability.

Here's what I found. It's actually pretty straightforward but right at then end Xcode threw me a curveball. I also had some trouble figuring out how I wanted to set up git around all of this but that's probably another post (I'm currently using git submodules, but I'm not a git expert. Let me know if you want to know what I did in Git. It took a few tries to get it all right.) This post is focused on Xcode. (All of this is correct for Xcode 6.0.1.) TL;DR: Xcode behaves badly if you try to add a project to a workspace while the project is open in another window. See my OpenRadar for more details.

The steps to a fancy framework!

  1. Pull all the code you want in your framework into a folder. I'd already done this: ~/code/HJSKit already existed.

  2. Create a new project, pick IOS->Cocoa Touch Framework.

  3. Add the files you want to the project. So far this is all completely normal.

  4. Here's where thing get interesting. The header files are actually listed as part of the target. In your Project Navigator select a header file and open the File Inspector. You should see it listed as a member of the framework but there's a new drop-down to the right that can change between "Project", "Public", and "Private". If you want the contents of the header exposed to app clients you have to change the header to "Public". For example, in HJSKit I have both HJSDebugCenter.h and HJSDebugMailComposeDelegate.h. While the apps need to see HJSDebugCenter the MailComposeDelegate is an implementation detail I'd like to hide inside the framework. So I set HJSDebugCenter.h to "Public" and left the other headers at "Project" level.

  5. You also have a new framework "umbrella" header that Xcode created. For me it's simply HJSKit.h. It has a comment that reads "In this header, you should import all of the public headers of your framework using statements like #import <HSJKit/PublicHeader.h>" This didn't work for me because that's not where I wanted the headers. I just went with vanilla #import "HJSDebugCenter.h" and it worked fine.

  6. Build this, make sure it all works.

  7. SUPER IMPORTANT: Now close the framework project window. If you don't do this Xcode will do something visually weird in the next step and you'll think you broke something.

  8. Open the project/workspace for the app client. Drag the framework's xcodeproj bundle into the Project Navigator. Make sure it drops as a top-level line, not indented under anything. (NOTE: this is where it gets weird for git. For git reasons I ended up with a copy of the HJSKit folder in each place. That's fine, just make sure you're referencing the HJSKit you really wanted.)

  9. Select the app target, go to Build Phases, and in the "Link Binary With Libraries" section click the + button. In addition to the usual iOS8.0 frameworks you'll now see a "Workspace" folder with your framework listed. Click it and you're good to go!

  10. NEW 2014-10-17: While you're in Build Phases add a Copy Files phase. Set the Destination to Frameworks, then click the + button. Select the framework from the Products folder of your framework project. See Using an Embedded Framework to Share Code for more on this step. We're not really sharing code in the sense of that article but we still need to do this step and I don't see it documented anywhere else. (The WWDC talk about Modern Frameworks doesn't show it either.) I didn't have this in the first version of this checklist and things ran on the simulator but not on hardware.

  11. NEW 2014-10-17: If your framework contains Swift code but your application does not there is a build Setting you need to configure on the app target. Under Build Options look for "Embedded Content Contains Swift Code" and set it to "Yes". This makes Xcode copy the Swift runtime into your app. Note you have to do this even if you don't call the Swift parts of your framework. The simple presence of a Swift file requires this or you'll get an error immediately in dyld_fatal_error saying that libswitCore.dylib can't be loaded. My framework didn't have Swift code originally so I didn't have this step in the first version of the checklist. If your app target itself contains Swift code then you don't need to set this Yes, as the runtime is already present.

  12. Now you can just put #import "HJSKit/HJSKit.h" in any source file and anything imported in the umbrella folder is available.

  13. You can repeat steps 8-10 for other projects, and each will get a copy. I currently have two workspaces for two different apps and each has a HJSKit framework included.

If you've read about how to hack this up in the past you'll notice what I didn't do: I didn't run lipo at any time, I didn't make an aggregate target, I didn't have to go fussing about and figure out where the Build folder is for the framework. Each app is building its own copy of the framework but that's the behavior I wanted. I have code completion from the framework in each app and the other git magic means I can push changes from one app to the other if I so desire, but I also have a version history where I can see that App A and App B are using different revisions of the framework.

Step 7 was the bugaboo for me. If you have the framework project open then the project file just sort of drops into the workspace without targets listed and isn't available when you go to "Link Binary With Libraries" in Step 9. If you close all the open windows and reopen the workspace it will work fine but I don't know why you'd know that without a lot of experimentation. After you have these all set up any other sequence I've tried to open both the workspace and the project simultaneously generates an error somewhere. But there's this one way that silently just does something broken. And it's the one that I was naturally trying yesterday because I kept thinking I had made the framework wrong, so I had the framework project open so I could tinker with it. It's basically a Heisenbug at that point.

Archiving an iPad only App

(I've submitted Combat Imp to Apple and while I wait for approval I'm doing some clean-up which includes verifying problems and writing up radars. There may be a handful of these posts coming up.)

Combat Imp is an iPad only project. Way back when I had just plunked some icons in manually (into the .plist I believe? It's been a while.) As I got ready to ship the damn thing I switched over to using an Asset Catalog for the icons and launch images. I only set up the iPad icons, because why include other sizes that wouldn't be used? And this was good.

At some point later in time I went to make an archive (inside Xcode - I was getting ready to make a beta build for testers.) The archive didn't have the nice icon, instead it had the generic grid/circles placeholder icon. Turns out that even in an iPad only app, the archive uses the iPhone iOS 7 icon and doesn't look for other icons if that slot is blank.

Not a huge deal but I was having some other icon problems at the time and I conflated two problems and went down a rabbit hole. So if your Xcode archive is lacking an icon, try adding an iPhone icon.

I wrote it up as radar 18252465 if somebody wants to dupe it. It happens on both Xcode 5.1.1 and Xcode 6 beta 7.

A Month of Kittens!

A month ago yesterday we picked up a couple of kittens from the local shelter. I've tweeted a few pictures but I thought it was time to introduce them here on the blog. I also pulled my DSLR memory card and got around to looking through the pictures I took the day they came home.

First off, here's Shenanigans:

IMG_3336

And here's Hijinks:

IMG_3370

If you like those images there's a bunch more on Flickr

I'll call out them meeting up on that first day:

IMG_0542

and wrap up my photo love-fest with a picture of them from just a few days ago:

IMG_0678

It's so good to have cats around the house again!

The Last (I Hope) Word on NSMutableCharacterSet

Edited to add 2014-09-05: Xcode 6 beta 7 emits a warning for assigning the NSCharacterSet to a NSMutableCharacterSet *. I've never received feedback from Apple on the matter but since it's caught now I marked the radar as resolved.

Edited to add 2014-03-07: Filed a Radar for this bug. I can't link to that, but I also filed it on [Open Radar](https://openradar.appspot.com/radar?id=5874203416854528).

Edited to add: Reading the code snippets in here is difficult. I can't find a quick & easy way to make them have horizontal scrollbars if I use a pre tag around it. Rather that have them be truncated I removed the pre tags for now so they word wrap. I'll bug Squarespace about it later.

This NSMutableCharacterSet bug! I keep poking at it, going "OK I guess that makes sense" and then a day later going "Wait. That can't be right." Quick review. The following line of code:

NSMutableCharacterSet* fakeMutableSet = [NSCharacterSet decimalDigitCharacterSet];

seems to work. But although the object you get will respond to NSMutableCharacterSet selectors it won't actually do anything. Specifically you can write this:

[fakeMutableSet formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]];

formUnionWithCharacterSet returns a void so you can't tell if it worked or not, and in fact it will not work. Conceptually now I should have a set with the decimal digits and whitespace. What I have (as far as I can tell, you can't probe much into NSCharacterSets) is the exact same set I had before this call. If you want a mutable copy you have to call mutableCopy like so:

NSMutableCharacterSet* mutableSet = [[NSCharacterSet decimalDigitCharacterSet] mutableCopy];

So far so good. I understand why I need mutableCopy, but at first I didn't understand why A ) fakeMutableSet wasn't mutable and B ) given that it wasn't mutable calling formUnionWithCharacterSet didn't cause an unrecognized selector assert. Seems like either it should be mutable or it shouldn't respond to the selector.

I finally got around to writing some test code and I've found enough that I'm convinced there is a real bug here and it's not at all what I suspected at first. I'll write this up in a radar after I finish this post. I've placed the source on GitHub if you want to follow along.

The full test code does a bunch of introspection on a variety of NSCharacterSet and NSMutableCharacterSet objects. But here's the smoking gun part:

NSCharacterSet* decimalSet = [NSCharacterSet decimalDigitCharacterSet];
NSMutableCharacterSet* fakeMutableSet = [NSCharacterSet decimalDigitCharacterSet];
NSMutableCharacterSet* mutableSet = [[NSCharacterSet decimalDigitCharacterSet] mutableCopy];

All three of these end up pointing at an instance of an internal class called _NSCFCharacterSet. So yeah. The docs say NSMutableCharacterSet is derived from NSCharacterSet but not really in the sense I think of it. And guess what: _NSCFCharacterSet responds to the NSMutableCharacterSet methods! See:

// So here's the catch right? _NSCFCHaracterSet can respond to formUnionWithCharacterSet but

// *DOESN'T WORK* if the underlying data is not mutable.

if ([[decimalSet class] instancesRespondToSelector:@selector(formUnionWithCharacterSet:)]) {

NSLog(@"Attempting union with decimal set");

// Have to cast this call to compile, but note no cast is needed for fakeMutableSet

// Also note this is NOT an unrecognizedSelector: we respond to this method

[(id)decimalSet formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]];

}

Admittedly, yes I have cast decimalSet so the compiler does not complain but I expected the runtime to skip the call because the instances shouldn't respond to the selector. Somewhere up inside formUnionWithCharacterSet there is code that says "if I'm not mutable just sort of fail silently." It would have saved me a ton of time if that had at least logged a line that says "this call didn't work".

So yeah, if NSMutableCharacterSet objects were really a different class than NSCharacterSet objects I would have had a compiler error when I wrote the offending line without the mutableCopy. If NSCharacterSet objects didn't have methods to responds to selectors from NSMutableCharacterSet then I would have had a runtime assert. The NSCharacterSet and NSMutableCharacterSet API's sort of falsely represent what the data does. I don't see anyway to catch this happening from my code. So if you're using NSMutableCharacterSet be careful.

Does this extend to other NSMutable* classes? I don't know. These are the only ones I use where there are a lot of "return a pre-populated instances" method so I'd have more trouble making a real world example using NSMutableArray or NSMutableDictionary.