Cerro Chirripó: The Roof of Costa Rica

January 3, 2012

Cerro Chirripó (12,533 feet)

24 miles hiked
7,546 feet of elevation gain
15 hours

I was recently vacationing in Costa Rica, so what better thing to do than climb the country’s highest peak?

After finishing a bunch of touristy activities in the Monteverde/Arenal areas, I made my way down towards the mountain. I caught a morning bus from San José (the capital) down to San Isidro de El General, a bus ride which follows one of the most treacherous sections of the Inter-American Highway. It passes over the 11,322-foot-high Cerro de la Muerte (Mountain of Death), with some spectacular views. The bus ride was supposed to take three hours, but it took closer to four, since apparently there was a bicycle race along the same road from San José to San Isidro the very same day.

I then took a taxi to San Gerardo de Rivas, the town at the base of the main trail to Chirripó, since I’d missed the bus there. I arrived at the National Parks Office around 3:45 pm on Monday afternoon.

Cerro Chirripó lies within a National Park, inside of which camping is not allowed. They do have a large hut, called Base Crestones, at about the 14.5 km (9 miles) mark along the 20 km (12 miles) trail to the summit, and it sleeps around 40 people or so (the exact number seems to vary depending on whom you ask—one person claimed it slept 60). Most people who hike Chirripó stay at the hut for a night and do the whole hike over two days, and many also stay at the hut for an additional night in order to hike other surrounding peaks.

I intended to hike it in two days, Tuesday and Wednesday. SummitPost claimed it was easy to get a reservation, but alas that was not the case. When I arrived on Monday, the office was all out of reservations for Tuesday night, and they only had three reservations available for Wednesday night, which could not be reserved until the office reopened Tuesday morning. Here’s how the reservations work, according to a local I talked to:

  • Twice a year (once for the wet season, once for the dry season), about 30 or so advance reservations are opened up for each day in the upcoming season
    • These can be reserved by phone (call the parks office at +506-2742-5083), but you need to pay in advance with a wire transfer to ensure the reservation
    • Some hotels and travel services like to reserve these tickets right away and then resell them to clients; I don’t know who they are or how to get them.
  • Every night, 10 tickets are available for reservation the day before. That is, if you want to stay on night X, you can reserve them on day (X-1) at the parks office in person.
    • However, if anyone is staying multiple nights, then there are that many fewer reservations available. For example, if seven people bought two-night reservations for nights X and X+1, then there will only be three reservations available for night X+1 on day X.
    • The parks office is open from 6:30 am–4:30 pm. If you want to be sure you’ll get a reservation for the following night, you need to get there by 4:00 am. I’m not kidding—there will be a dozen people there by the time the office opens at 6:30.

So, after digesting all of that, I weighed my options. It was currently Monday afternoon, and I had to be on a plane leaving San José Thursday morning, which meant I had to be back to San José on Wednesday night. Sleeping at Base Crestones on Wednesday night was not an option.

Clearly the only sane thing to do was to hike it all in one day.

I could either hike it on Tuesday or Wednesday. But by the time I figured out what to do, the parks office was already closed for the day. I’d have to wait until Tuesday morning to get a permit to enter the National Park (you still need to buy a $15/day permit to enter the park, regardless of whether or not you’re staying at Base Crestones). I chose to hike it on Wednesday.

I went to bed early on Monday night to start shifting my sleep schedule as much as I could for an alpine start. Tuesday morning, I got up early, met the crowd waiting to get into the parks office, learned all about the reservation system, and bought a day pass to the park for Wednesday. I spent the rest of the day wandering around town, picking up some supplies, and relaxing.

Tuesday night I went to sleep around 7:30 pm at the Hotel Uran, which is about 50 meters from the trailhead in San Gerardo. I highly recommend staying there—for about $18/night for one person, you get a private room and hot showers (in a shared bathroom), and the restaurant there is also really good and cheap, too. I set my alarm for 11:45 pm, with the intention of starting hiking at the stroke of midnight.

But for whatever reason, I woke up an hour before my alarm clock. Instead of rolling over and trying to get another hour of sleep, I decided to get up and hit the trail, in true alpine start fashion. The entrance to the National Park isn’t until the 4 km mark, so as long as I didn’t get there before midnight, I’d be all in the clear as far as my permit was concerned (not that there’s anyone checking permits there—the only place they check them is at the Base Crestones hut).

The hiking for the first several kilometers was not particularly notable, it was a fairly steady climb upwards. At several points along the way, I could see the distance lights of a city, and the stars were gorgeous, but otherwise there wasn’t much to see in the glow of my headlamp beyond the trees right in front of me.

The trail has a signpost almost every kilometer up to the Base Crestones hut (a few are missing), along with a cute name for that section of trail. The trail is graded for horses, so it’s never too steep, but it’s not shallow either. There’s a porter service in town which will carry up your supplies by horse (for a fee) to Base Crestones the day before you get there, if you’re not sporting enough to carry it yourself. There are frequent sections of the trail where it’s divided into two parts, one for people and one for horses. The people sections have these nice staircases made of tree stumps, along with a railing and some posts to prevent horses from going in them, while the horse sections are extremely muddy and full of big, wet postholes.

Chirripó trail map

Chirripó trail height profile

I plowed along at a pretty steady pace of 25 minutes/km, stopping briefly every hour or so to chow down on an energy bar. Just after the 7 km mark, there’s this other shelter called Llano Bonito (Beautiful Plain). You’re not supposed to sleep there, but it can be used as an emergency shelter (which seems odd to me, since it’s a fairly large two-level four-walled building). It has a potable water supply there, as well as a trough for horses. Until then, there were no water supplies at all, not even little creeks. When I got there, I topped off on my water, downed an energy bar, and continued onwards.

Around 12 km came Monte Sin Fe (Hill of No Hope), which was the first non-trivial local maximum along the trail. There was a short downhill section afterwards and then it was up, up, and up again.

Finally at 14.5 km, I made it to the Base Crestones hut around 5:00 am. It was still dark out, and I hadn’t seen another human soul all night. I still didn’t see any other headlamps in the distance coming from hikers trying to make it to the summit for sunrise.

The sun started rising at about 5:30, as I was making my way through the comparatively flat section of Valle de los Conejos (Valley of the Rabbits) just beyond Base Crestones. There was a bit of frost on the alpine grass, crunching under my feet as I walked by, but it didn’t feel cold at all because I’d been staying moving almost continuously.

Valle de los Conejos

I put my headlamp away as the sky started brightening up. Miraculously, it lasted all night. I don’t remember when the last time I changed the batteries was, but I’ve definitely used it on numerous occasions for considerable amounts of time. I did have extra batteries with me, just in case. I expect I’ll need to use them the next time I need my headlamp.

I was starting to slow down noticeably here. I was walking more slowly and taking more frequent breaks. This was probably due to the elevation—I didn’t feel like I had any serious symptoms of altitude sickness, but it must have been having an affect on me. After following the trail around a nearby peak, I finally caught a glimpse of the summit, as well as some other people making their way down. The last 500 meters or so are rather steep, with a bit of scrambling (considerably steeper than anything else on the trail), but nothing I wasn’t used to from the rugged White Mountains of New Hampshire. I’d say it was comparable to a short section of the Webster Cliff Trail.

At 6:56 am, I summited Cerro Chirripó, and found myself on the roof of Costa Rica. The views were incredible! They say that on an exceptionally clear day, you can see to both the Atlantic and Pacific Oceans. This was not one of those days—there were too many clouds to see either ocean. I snapped a bunch of pictures, signed the summit register, ate my “breakfast”, and chatted with the other hikers there. One of them was even kind enough to share a swig of some rum he brought up with him.

After about 40 minutes on the summit, I started making my way back down. When I got back down to Base Crestones, I went in to use their toilets, which they let me do as long as I showed them my pass to the park (if you don’t go inside, nobody will ever ask for your pass). I also ashamedly checked my email on my smartphone—can you believe they have Wi-Fi up there? And it was actually reasonably fast.

The hike back down went faster than the hike up, not too surprisingly, but with about 8 km left to go, my legs started becoming uncooperative. All of the downhill hiking was doing a big number on my knees, and it was getting increasingly painful to keep walking downhill. My pace slowed down massively, and I started taking numerous sitting breaks to stretch and rest.

At long last, I stepped off of the trail around 2:00 pm, weary and sore. I quickly made it back to my hotel and took a nice hot shower. I packed my things, checked out of the hotel, grabbed a bite to eat, and started making my way back down the road to the bus stop in town. It was still another almost 2 km downhill, but the shower had rejuvenated me, so it wasn’t too bad.

I got on the 4:00 bus back to San Isidro, but the adventure wasn’t over yet. The bus managed to get a flat tire partway through, so we all had to sit there for about half an hour as the driver replaced it with a spare. The roads there are very hilly, bumpy, and in this case, unpaved.

When I arrived in San Isidro a little before 6:00 pm, they informed me that the next available bus to San José was not until 8:30, so I grabbed some food and wandered around the town center for a bit. Out of curiosity, I asked a taxi driver there how much it would be for a ride to San José, and he told me $160. I’d easily wait a couple of extra hours rather than pay that amount, so that’s what I did.

I was perusing an ice cream shop next to the bus station when a stranger approached me and asked where I was going (I was toting around a suitcase in addition to my backpack). When I said San José, he told me he’d take me there for $10. I thought it must have been some sort of scam, but he explained that he was a taxi driver based out of San José and was going back there anyways, so he was hanging around the bus stop trying to snipe off a couple of fares for the ride back. He had an official taxi (red with a yellow triangle), so I agreed to go with him since I wanted to get back at a reasonable hour. He wanted to get at least one other rider with him, though, so we didn’t leave right away.

After waiting for a while without anyone else, he said he’d take me back for $20, leaving right away. Again since I wanted to get back, I agreed, so that’s what happened. We went back over Cerra de la Muerte, and I got back to my hotel not too late to get a decent night’s sleep. The next morning, I got another taxi to the airport, and I was on my way home.

A smashing success.

0

Debugging a strange iTunes permissions problem with DTrace

November 27, 2011

The other day, I noticed that one of my media files wouldn’t play in iTunes because it decided that my computer wasn’t authorized to play it. I could not authorize my computer to play that song, however, because the iTunes account name associated with that song no longer existed—I had changed the email address of my account in between the time that that was purchased and when I transferred it to my current computer (it was purchased prior to iTunes’ releasing all of their music DRM-free; I strongly oppose DRM).

When I attempted to re-download the track from the iTunes Store, it gave me this error message which would ordinarily be pretty helpful:


iTunes couldn’t download your purchase.

You don’t have write access for your iTunes Media folder or a folder within it. Change permissions (in the Finder) and then choose Store > Check for Available Downloads


Alas, that was not the problem. Nothing I can think of would have messed up the permissions, and find(1) confirms that all of the subdirectories there are owned by me and are readable, writable, and executable:

$ cd ~/Music/iTunes
$ find . \! -user $USER
$ find . -type d \! -perm -0700
$ # No output from the above commands

What’s going on here?

Time to dig deeper with DTrace. DTrace is a powerful debugging tool, useful for answering such questions as “What system calls is this process calling?”, “Why is the performance of my server so horrendous?” and many more. It’s like strace on crack.

But with great power comes great complexity. In order to use DTrace, you need write a short program in the tool’s D programming language (not to be confused with that other D programming language). The program can be written on the command line or in a separate text file, but it’s still non-trivial. Some really useful examples can be found here, in addition to the various examples in the documentation.

The error message from iTunes strongly smells like a call to open(2) is failing with EACCES when iTunes tries to create the re-downloaded media file. Let’s see if that’s the case:

syscall::open*:entry
/pid == $target/
{
  printf("%s %s 0x%x 0x%x", execname, copyinstr(arg0), arg1, arg2);
}

syscall::open*:return
/pid == $target/
{
  printf("errno=%d", errno);
}

Get the PID of iTunes, start tracing it with sudo dtrace -s open.d -p $PID, and try to download the file again. Unfortunately the output is not expected—errors like this get printed many times:

dtrace: error on enabled probe ID 6 (ID 120: syscall::open:return):
 invalid user access in action #2 at DIF offset 24

After a little more digging, I discovered that iTunes does not like getting debugged, which probably means it also doesn’t like getting itself traced—it just makes the debugger segfault instead. Fortunately, it’s not too hard to get around this: just turn ptrace into a no-op in iTunes when it tries to make itself undebuggable with ptrace(PT_DENY_ATTACH). Charlie Miller provides a nice gdb script for doing so:

break ptrace
condition 1 *((unsigned int *) ($esp + 4)) == 0x1f
commands 1
return
c
end

Ok, so we’re past that hurdle. Quit iTunes, restart it under gdb with this anti-anti-debugging technique, fire up DTrace again, and try to re-download the file:

CPU     ID                    FUNCTION:NAME
  0    119                       open:entry iTunes /.vol/234881026/1516872/SC Info.sidb 0xa00 0x1b6
  0    120                      open:return errno=13

Hmm. Error 13 is indeed EACCES, but what is this strange file under /.vol? Why, it’s the Volume Management file system, used by the Carbon File Manager. Using ls -al /.vol, it appears that that directory is completely empty, yet somehow other file accesses within there succeeded, as indicated in the DTrace output.

I’m not sure if there’s an easy to figure out which directory in the real file system that /.vol/234881026/1516872 refers to, but a quick search for a file named “SC Info” yields two likely candidates:

$ locate -i "SC Info"
/Users/Shared/SC Info
/Users/Shared/SC Info~orig

Let’s see what those directories look like:

$ ls -la /Users/Shared/SC\ Info*
/Users/Shared/SC Info:
total 0
drwxr-xr-x   2 root  wheel   68 Jul  2  2010 .
drwxrwxrwt  10 root  wheel  340 Oct 30 22:54 ..

/Users/Shared/SC Info~orig:
total 0
drwxrwxrwx   2 adam  wheel   68 Jul  2  2010 .
drwxrwxrwt  10 root  wheel  340 Oct 30 22:54 ..

Aha! So iTunes is trying to create a file named SC Info.sidb in /Users/Shared/SC Info, but it’s failing because I don’t have write access to that directory.

The solution:

sudo chmod a+w /Users/Shared/SC\ Info

Bingo! The song now downloads successfully.

Of course, you probably could have skipped all this, googled the error message, and found this knowledge base article explaining how to fix it without too much trouble, but that’s boring. Using DTrace to debug the problem is much more fun and exciting!

Do you have any great success (or failure) stories involving DTrace?

0

Google search keyboard shortcuts

October 10, 2011

For quite some time, Google’s experimental search offered a “Keyboard shortcuts” experiment, where you could navigate search results with vi-style key bindings (j and k to navigate up and down search results, o or Enter to open a link, and / to move the cursor back to the search box).

It seems they have recently removed that experiment, as they sometimes do. I don’t know exactly when that happened, but The Wayback Machine puts it at somewhere between April 21 and now. But despite Google’s removing the experiment, the keyboard shortcuts had still been working just fine for me—until, that is, I revisited the page linked to in the first paragraph. Even just visiting that page, without taking any action, removed the shortcuts. The Accessible View experiment also provides similar keyboard shortcuts, but it does other things I don’t like, such as highlighting the currently selected search result blue.

I took a peek into the JavaScript on that page, and though it was optimized and obfuscated, it wasn’t enormously complicated. It was doing stuff with the PREF cookie, but the cookie’s content was highly opaque. There was a handy _toggle() function which took the name of a feature to toggle. The two currently available experiments, Instant on Images and Accessible View, which pass in the names 'ImagesInstant::PublicOptIn' and 'Axs' to _toggle(). Archive.org tells me that the keyboard shotcurts experiment used the name 'BetaShortcuts'.

So, the obvious next step was to see if running _toggle('BetaShortcuts') on that page would fix up my cookie to give me back my keyboard shortcuts. I fired up the web console from Firefox’s Web Developer add-on and ran that command:

> _toggle('BetaShortcuts')
TypeError: h("e_" + b) is null

D’oh. It’s trying to do something with the page’s DOM—ordinarily, when you click the “Join this experiment” button, it changes the button text to “Leave this experiment”, but there’s no button for the BetaShortcuts experiment to change the text for. The h() function is just a thin wrapper around document.getElementById(). Well, let’s try hacking around this by renaming one of the other buttons:

> h("e_Axs").id="e_BetaShortcuts"
"e_BetaShortcuts"
> _toggle('BetaShortcuts')
undefined
GET http://www.google.com/url?(various opaque parameters) [HTTP/1.1 204 No Content 88ms]

Close the page, and voila! Keyboard shortcuts work again.

11

Bastion

September 6, 2011

A gem of a game called Bastion came out earlier this summer, and I recently finished getting all 200/200 of its achievement points. If you have an Xbox 360 or Windows PC, I highly recommend checking out the demo at the very least, and for $15, it’s easily worth its cost. Sadly, Mac OS X and Linux users are out of luck for the time being (it doesn’t seem to run under Wine).

Bastion box art

Bastion is an action RPG, in a similar vein to the Diablo series, but the RPG mechanics are much simpler. You only have weapons and potions to worry about—there’s no armor/rings/etc. to worry about, no complicated skill trees. The set of weapons that you find throughout the game is fixed, not randomized, and you can upgrade the weapons for a cost. Potions provide passive benefits (such as increasing your chance of critical hits when low on health), and you can carry more potions as you level up.

Three things really make this game shine and put it on another level from your typical hack-n-slash game:

  • The narration—Logan Cunningham narrates the game, and he does a phenomenal job of it. Not only is he a great voice actor that really adds character to the game, but the narration is dynamic, based on what you do in the game. When you walk off the edge of the world for the first time, he comments “…and he falls to his death. (pause) Nah, I’m just kidding with you.” Check out the trailer videos for a sampling.

  • The artwork—it’s just plain gorgeous. Supergiant Games obviously put a lot of love in this one.

  • The adaptive difficulty level—you can make the game harder for an additional challenge. But it’s not your usual “pick easy, medium, or hard for your difficulty level and stick with that throughout the game”. Instead, the game starts off at a particular difficulty level, and when you reach a certain point in the game, you can make it harder in smaller increments.

    There are 10 gods in the game, and activating each god makes the game harder in a certain way. One god makes enemies more resilient to damage, another makes them hit harder, another makes them move faster, another makes them regenerate health, yet another makes them randomly deflect attacks, and so on. Playing with more gods activated increases the risk but also the reward—you earn more experience and money by playing with more gods. This unique system makes a fantastic addition to the game.

My only complaint is that the game is too short. The “New Game Plus” feature—which allows you to replay the game after beating it, starting with all of your weapons, weapon upgrades, experience, items, etc. from the end of the game—adds some replay value, but not a huge amount. I got maybe 12-15 hours total of the game, and I’d easily pay $60 for 40+ hours of gameplay.

Bottom line: 9.5/10

0

Owl’s Head Adventure

May 16, 2011

This past Saturday, May 14, I attempted to summit Owl’s Head, a mountain in the Pemigewasset Wildernass of the White Mountain National Forest in New Hampshire. It’s one of the most remote of the Four Thousand Footers.

The shortest route to Owl’s Head from any trailhead is via the Lincoln Woods Trail. From there, it’s 9 miles each way, making for a non-trivial 18 mile day. However, since that trail has some tough river crossings, we decided to do some bushwhacking to avoid those. We took the Black Pond Trail, and from Black Pond (pictured below), we bushwhacked for about a mile north to where the trail to Owl’s Head crosses back onto the south side of Lincoln Brook (variation “A” in the map linked to above).

We followed the trail for another few miles until it crossed the brook again. Tried as we might, we couldn’t find a suitable route across the brook, so we reluctantly took our boots off and waded through. Let me tell you, that water was cold. There’s still plenty of snow melt this time of year (and plenty of snow at higher elevations). We thought that that was the only water crossing left, according to the map. We were wrong—the brook has an unmarked fork, so there was a second crossing that we were forced to wade through.

By around 12:45 pm, we had finally made it to the fork for the trail going up to the summit of Owl’s Head, which was not marked by any signs. The only indications of the trail were two smallish cairns placed a trail’s width apart next to two parallel logs pointing up the mountain. Up until this point, the hiking had been almost entirely flat. Now, the trail shoots up 1500 vertical feet over 1.1 miles, an average grade of about 26%. On the plus side, though, we finally saw some fantastic views that weren’t of the river:

Shortly after beginning the steep climb up the loose scree, we came across the first people we’d seen all day since Black Pond. Coming down from the summit of Owl’s Head was a group with a blind man! They were of course slow-moving, as the blind man had to be carefully guided down the mountain, but it was an impressive feat nonetheless. They had camped out at the base of the mountain the night before and had taken a huge chunk of the day to go up and down that 1.1 miles.

The afternoon went on, and we found a stream of water pouring down the narrow trail. It was getting late, and the weather forecast was calling for rain. So although we were probably only about an hour away from the summit, we made the wise decision to turn around and head back home. It’s painful to come so close to the summit and not make it (especially one so remote), but I think it was the right decision. We still had another 8 miles of hiking ahead of us, including two stream crossings and more bushwhacking.

On the way back, we passed by the group with the blind man again around the stream crossings. They also had a dog with them (whom I presume was the blind man’s seeing-eye dog but was not acting in that capacity for the hike) who made it across the first crossing but couldn’t make it across the second. The poor dog had this horrible fear in his eyes and sadly had to be carried across.

When we made it back to the the next stream crossing that we had avoided by bushwhacking, we again went off trail with the goal of avoiding unnecessary wading. We could have attempted to retrace our steps back towards Black Pond, but the difficulty with that is that if we were off by just the smallest amount, we wouldn’t hit the trail and would have to bushwhack far more to find our way back onto it. Instead, we bushwhacked along the bank of the river (variation “B” of the aforementioned map, in reverse). It’s a slightly longer bushwhack, but it does not require pinpoint navigation.

1.5 miles or so later, we came out of the woods at Franconia Falls:

As we started following the trail back out to the Lincoln Woods parking lot, we came across a curious sign that said only “200 Feet” on it. We were a little confused as to its meaning, until a short while later when we saw another sign inquiring if you knew how much 200 feet was—in the Pemigewasset Wilderness (and many other parts of the WMNF), camping and campfires are prohibited within 200 feet of trails and waterways. The signs were demonstrating that 200 feet is farther than you might think.

We hustled through the final few miles back to the car, as it was really starting to rain considerably. We finally made it back to the car sopping wet at 7:00 pm, completing about 16 miles or so in just under 11 hours. We were sure glad we turned around when we did!

I’ll definitely have to come back to Owl’s Head some time if I’m to finish hiking all of the Four Thousand Footers, but after this adventure, I’m putting it down near the bottom of my list. It’s very remote, it has numerous stream crossings, and the trail is poorly maintained (I think we saw a grand total of two blazes and one arrow painted on a rock on the entirety of the trail between where we joined it after the bushwhack and where we turned around).

Stay tuned for more updates on the Four Thousand Footers, I have plans to hit many more this summer.

0

Algebraic Crosswords

April 24, 2011

A blogger by the name of T Campbell recently posted an interesting read about Algebraic Crosswords. And at the end, T posts a $100 bounty for a computer program to help crossword constructors construct such crosswords. That’s right up my alley as both a programmer and a puzzle solver, so I threw together a quick Python script to do the job.

My program, named algxword, can be downloaded here.

The usage is as follows:

Usage: ./algxword.py [OPTIONS...] WORDLIST FROM TO

Finds all words in the file WORDLIST (which need not be sorted) which would
continue to be words when substituting the substring FROM for the substring TO.
Only words which contain FROM in them are considered.

Both FROM and TO can be empty strings.  If FROM is the empty string, then TO is
added at each position in the string to test for a word.  If TO is the empty
string, then the FROM string is simply deleted.

Ordinarily, only the first occurrence of FROM is replaced with TO.  If the -a
option is specified, then all occurrences of FROM are replaced with TO.

OPTIONS:

-a      Replaces all occurrences of FROM with TO when testing for a word
--help  Prints this help message

Examples:

# Find all words which remain words when substituting the first occurrence of
# 'qu' for 'k' in the word list /usr/share/dict/words
python algxword.py /usr/share/dict/words qu k

# Same as above, but replace all occurrences of 'qu' for 'k'
python algxword.py -a /usr/share/dict/words qu k

# Find all words which can have an 'lax' inserted in them
python algxword.py /usr/share/dict/words "" lax

More detailed instructions for the less command line-savvy can be found in the included README file.

5

Boston Crossword Puzzle Tournament

April 14, 2011

On Saturday the 23rd (just over a week from now), I’ll be participating in my first ever crossword puzzle tournament, the Boston Crossword Puzzle Tournament. I don’t expect to come close to winning; it’s mostly just for fun. Hopefully I’ll meet some neat people there.

In the distant past, I’d been a very occasional crossword solver. I only ever did the weekday Boston Globe puzzles (which are syndicated from the Universal Crossword), and not with any regularity. Like most solvers, I was pretty bad at them for a while, what with not knowing common crosswordese and tons of bygone pop culture, but I slowly improved over time.

Over the past couple of years, I’ve been solving puzzles more regularly and getting better. I now regularly solve the Universal Crossword and the New York Times crossword. The Universal I can almost always completely solve (sometimes I need to Google one or two things if there happens to be two obscure answers crossing each other that I don’t know). I’ve gotten my times down to about 4-6 minutes or so on average, and my best time is 3:19.

The NYT, on the other hand, is still a huge learning experience for me. Those puzzles increase in difficulty through the week, with Monday’s puzzle being the easiest and Saturday’s being the hardest. Sunday is special, in that it’s usually on about the level of a Thursday puzzle, but much larger—21×21 instead of 15×15.

Monday puzzles solve like Universal puzzles for me; Tuesday puzzles nearly so, but they’re slower and take more thinking. A Wednesday puzzle I can finish about 2/3 of the time and get about 80% of the puzzle the other 1/3 of the time. Thursday and Sunday puzzles I can fill in about half of on average before resorting to Google and Wikipedia. Friday and Saturday puzzles are absolute nightmares—I can rarely get more than a small handful of clues without turning to the Internet, and even then, the difficult cluing makes them quite the challenge. But armed with my arsenal of Google, Wikipedia, grep, One Across, OneLook, and more, even the mighty Saturday puzzles fall within an hour or so.

I’ve also been participating in Matt Gaffney’s Weekly Crossword Contest for the past couple of months, ever since I found out about it from reading Rex Parker’s blog (who does an awesome writeup of every day’s NYT puzzle). Matt’s puzzles are a lot like the puzzles from the MIT Mystery Hunt. Each week’s crossword contains in it some hidden word or phrase that is the answer to the puzzle. The extraction mechanisms are different in every puzzle, so figuring them out is a real challenge. If you’re not familiar with Mystery Hunt-style puzzles, go check out Matt’s blog for examples of how previous puzzles have worked. I highly recommend solving his puzzles if you’re at all into crosswords or the Mystery Hunt (and doubly so if you’re into both).

The Saturday of the weekend after the Boston Crossword Puzzle Tournament is DASH3 (Different Area—Same Hunt), a Mystery Hunt-like competition that takes place in parallel in multiple cities across the country. Another highly recommended event for avid puzzlers. I’ll be competing in the Boston edition.

There’s not really a punchline to this post, it’s more just my musings on puzzles. Did I mention I like puzzles?

0

The tricky inline specifier in C99

March 21, 2011

Try to compile the following simple C program in C99 mode with GCC:

inline void foo() {}
int main(void)
{
  foo();
}

The results may surprise you:

$ gcc test.c -std=c99
/tmp/ccWN4GRh.o: In function `main':
test.c:(.text+0xa): undefined reference to `foo'
collect2: ld returned 1 exit status

Huh? The function’s right there!

Well it turns out that this is not a bug in GCC, but a peculiarity in the way the inline keyword is defined by the C99 standard. Basically, a function declared inline without either of the extern or static linkage specifiers only creates an inline definition of that function, not an external definition.

When presented with a call to such a function, the compiler can choose to call either the inline definition or the external definition. If it chooses the external definition, and such an external definition doesn’t exist, we get a linker error, as in the above example. In the dry words of the standard:

ISO/IEC 9899:1999 §6.7.4/6:

Any function with internal linkage can be an inline function. For a function with external linkage, the following restrictions apply: If a function is declared with an inline function specifier, then it shall also be defined in the same translation unit. If all of the file scope declarations for a function in a translation unit include the inline function specifier without extern, then the definition in that translation unit is an inline definition. An inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit. An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition.120)

So there are three ways to fix this code:

  1. Give foo internal linkage (by declaring it static) and avoid the above clause entirely

  2. Declare foo as extern
  3. Provide a separate external definition for foo in another translation unit (that is, another source file)

I would strongly recommend against solution #3, since then your code base will have two separate definitions of foo, which will be very confusing for people reading your code. It’s very easy for them to get out of sync, if somebody changes one definition but forgets to change the other, which makes for some insidious bugs (such as working correctly in a debug build but not in a release build, or vice-versa).

If your inline function is defined and used only in one source file (as in our toy example), solution #1 is the way to go: just give it internal linkage. No reason to make it world-accessible.

Conversely, if your inline function is defined in a header file so it can be used throughout your code, it makes more sense to give it external linkage. Go with solution #2:

extern inline void foo() { /* body */ }
0

Hey look I shipped another game

February 7, 2011

This past Tuesday, February 1, marked the release of my 3rd Rock Band track pack and my 4th Rock Band title overall:

The sequel to the hit game Rock Band Country Track Pack, Country Track Pack 2 brings you such songs as Dwight Yoakam’s country rap “Intentional Heartache” that involves spraying various things neon green:

At one point during development, we had a bug relating to the scoring of the “talky” vocal parts of that song beginning around 2:55. So unlike most other bugs, we couldn’t use autoplay for testing and debugging—we actually had to sing. Normally this isn’t a problem for our QA team, who sat in a different room (they got to be really good at singing the songs in the game), but for the developers, it was a whole different story. The lyrics to the song are so ridiculous (if you haven’t watched the video above, you really should), that every time we picked up the mic to test something, it brought the productivity of everyone else in the room (including much of the Shoot Many Robots team) to a screeching halt.

Another interesting thing to note is that while all of the previous track packs have shipped on the PlayStation 2, this was the first track pack not to do so; it only shipped on the PlayStation 3, Wii, and Xbox 360. I don’t know why that decision was made, since the game is based on the original Rock Band 1 engine, which runs just fine on the PS2. My guess is that the PS2 sales of the previous track packs were so low that the revenue from that platform did not outweigh the cost of licensing, manufacturing, and distributing it, but that is purely speculation.

With 3 track packs under Demiurge’s belt, I cannot comment on whether or not any further track packs are in development. I can neither confirm nor deny the existence of Rock Band Metal Track Pack 2, Rock Band Country Track Pack 3, Green Day: Rock Band 2, Rock Band Emo Track Pack, Rock Band Japanese Hip-Hop Track Pack, or Rock Band Alternative Punk Acid Black Death Metal Calypso Pop Extreme Edition Track Pack.

0

Announcing Shoot Many Robots

October 13, 2010

I think the title of Demiurge Studio’s new game speaks for itself:

Ok, so that teaser trailer only raises more questions than it answers, but rest assured that this game will involve the shooting of many robots. Many many many robots.

Check out IGN for an interview with studio director Al Reed and the official website, and follow us on Twitter to keep up-to-date on all of the latest news on Shoot Many Robots.

0