Stir Fry Blues

Video Games

Stir Fry Blues

Last year I made a little game for Space Cowboy Jam with my good friend Matthew Breit. Inspired by one particular scene from Cowboy Bebop, we decided to make a silly cooking simulator. He modeled some vegetables, I coded some menus, we wrote some goofy dialogue, and slapped together Stir Fry Blues in a couple of weeks.

Sadly, the version we made within the time constraints of the game jam was pretty lousy (we placed 45th out of 60 overall.) It had no audio, the menus were ugly, and the NPC dialogue was repetitive. Most egregiously, we still had a placeholder screen for the cooking animations. After the jam, we simply left the project in unfinished limbo for months.

Over the Christmas holidays, I took a pass at improving Stir Fry Blues to the point that I would no longer be ashamed of it. I cleaned up the UI, added some creative-commons audio, and wrote logic for the NPCs to recognize over 30 recipes. To make the cooking animations, I took what we already had (3D modeled food) and simply added physics. Watching a loaf of bread boiling in a pot adds immensely to the game’s humour.

You can play Stir Fry Blues in your browser with the Unity Web Player, or download it:

Play Stir Fry Blues (

Download (Windows)

Download (Mac OSX)

Though I’m quite proud of the final product, making a game that’s entirely menu-driven and has lots of custom content isn’t actually much fun. Writing the data structures for the ingredients (their prices, taste values, expiration, etc.) felt like I was developing CMS software. At least I learned a lot about C# and Unity while doing so! For my next side project, I’d definitely prefer to tackle a more mechanics-driven game.

→ No CommentsTags:  ·  · 

So Many Twitter Bots

Internet, Programming

Since making @HoroscopeBot and @EveryBookBot, I’ve been on what you might call a bot-making rampage. I’ve really enjoyed tinkering with tiny scope coding projects that can be finished over a weekend, as opposed to my game-making side projects that often take months. Here, briefly, are five new bots I’ve assembled over the last few weeks:

@RandomChessBot plays random chess moves until it finds a checkmate, then tweets the final board state. This bot was particularly easy to code thanks to Jeff Hlywa’s excellent chess.js library, which provides a list of legal moves and exports the board state in ASCII. It’s worth noting that the majority of random chess games do not end in checkmate, but rather in an “insufficient material” draw state (the bot disregards these results.)

My friend Peter Javidpour made an amazing website called See Hear Party, which plays GIFs in time with the beat of a song (using Giphy & SoundCloud). As soon as he demoed it, I immediately wanted to help promote it with a Twitter bot. @SeeHearPartyBot pairs three random GIF search terms with a random electronic song from SoundCloud, occasionally creating an affecting juxtaposition or serendipitous harmony. This was also the first bot I implemented in Python instead of JavaScript.

@GameOfLifeBot tweets GIFs of Conway’s Game of Life simulated for 100 generations from a random initial seed. I used Tristan Hearn’s game of life library; since his implementation uses matplotlib, it was easy to export each generation as an image using various colour maps. I then used images2gif to assemble the individual frames into an animated image. This bot has inexplicably been my most popular bot since @HoroscopeBot; maybe people just like GIFs?

I noticed that Twitter has an official account that follows every verified user (a.k.a. “key individuals and brands”). This gave me a silly idea for a bot that tweets the out-of-context descriptions from the bios of random verified accounts. Fortunately this concept only took a few hours of coding to get up and running, and @VerifiedBioBot was born.

My most recent Twitter bot is @TinyCrossword, and it’s a personal favourite. It generates tweet-sized crossword puzzles, drawing clues from Simple English Wikipedia. For a tweet with an image (117 characters remaining), each clue can be no more than 36 characters long. It creates a new puzzle every day at noon PST, then tweets the solution a few hours later. This bot also scans the replies it receives, and will credit the first person who solves the puzzle correctly (sadly, nobody has yet to do so). I’m glad that I finally came up with a bot idea that was interactive!

These five new bots bring my total to eight. Sadly these will also be my last, at least for now. I’ve been using these short development cycles to procrastinate one some of my larger side projects. Making bots has been extremely entertaining and valuable, but I’m ready to get back to some meatier long term endeavours.

Also, if you’re interested in bots, be sure to check out the livestream of Darius Kazemi’s Bot Summit 2014 this weekend.

→ No CommentsTags:  ·  ·  · 

The Loot Cave

Video Games

Destiny Loot Cave

“The social experience of a cave farming run is amazing: the herding to get a team of Guardians all behind the line and firing in the right direction, the rush to grab the loot, the scramble when the panic wave starts, the beckoning glow from inside the cave. The speed at which the community organized around this activity was inspiring and humbling to us.”

- Destiny Dev Notes

Destiny’s loot cave is a fascinating phenomenon that has captured the interest of many journalists, critics and players. From a design perspective, it’s a potent example of emergent gameplay: the often unpredictable consequences that arise from complex interactions between individual game mechanics. I’d like to examine the details of how the loot cave works, speculate why it was difficult for Bungie to anticipate, and examine several options for fixing it.

The infamous cave is found in the Skywatch area of Destiny’s Old Russia level. The site would be unremarkable except for the gangs of high level players who (used to) hang out nearby. However, its unique geometry and the NPCs’ interactions with it are the key to what affords this particular exploit. The cave is a spawn point for low level Acolytes and Thralls, and its deep concave structure seems designed to obscure their reappearance from the player’s view. Once spawned, these creatures charge directly towards their intended combat zone on top of a nearby hill, disregarding incoming fire while in transit.

In Destiny, enemy NPCs are blocked from respawning if a player is nearby. However, the rolling hills that face this area allow players to see into the cave from a great distance. This means that player can stand outside of the range that would prevent respawning, while still firing into the cave with long-range rifles. Appearing under the player’s scope within a confined space and immediately charging towards the cave mouth, the enemies can be mown down over and over with ease.

This exploitative cycle is somewhat fragile, as it depends on the players’ ability to contain the flood of respawning NPCs within the bottleneck at the mouth of the cave. If an inopportune reload or lapse in concentration allows an enemy to escape the cave, the NPC can run free towards its destination and out of view of the ridge of snipers. Each enemy that escapes reduces the number that are spawning within the cave, diminishing the drop rate. A single player would therefore have great difficulty sustaining the loot cave; it requires two or more high level players diligently concentrating their fire. Given its reliance on the unspoken cooperation of strangers, it’s not surprising that Bungie was unable to anticipate this unusual tactic.

Map of the Loot Cave

Why would high level players opt to use this repetitive tactic, rather than participate in advanced missions as the developers intended? Firstly, there’s the unusual decision by Bungie that any NPC is eligible to drop legendary weapons and armour, even enemies that are significantly lower level than the player. Secondly is the fact that Destiny’s loot system is notoriously stingy. In the recent developer notes, Bungie had acknowledged the fact that their high level encounters and daily missions lack fanfare when loot is obtained. Furthermore, many of their systems offer faction reputation as a reward, an abstraction from the loot itself that may be difficult for players to grasp. It’s therefore understandable why some would prefer the tangible rewards and strong shiny feedback of the loot cave.

We can further examine the loot cave through the MDA framework, where mechanics describe the formal rules of the game, dynamics describe the rules acting in concert and responding to player input, and aesthetics describe the player’s experience of the game. Through this lens, the loot cave interaction looks like this:

  • Mechanic: NPC respawn points are blocked by proximity, but not line of sight.
  • Mechanic: Individual NPCs in Skywatch respawn 6 seconds after dying.
  • Mechanic: Any NPC can drop legendary items regardless of level.
  • Mechanic: Advancement beyond level 20 is only possible through gear.
  • Mechanic: Ambient multiplayer allows players to meet up randomly.
  • Dynamic: The Loot Cave™
  • Aesthetic: Periodic excitement from loot drops, boredom from repetition.

Last Thursday, roughly a week after being widely discovered, Bungie published a small hotfix to greatly decrease the efficiency of farming the loot cave. This was accomplished by “normalizing” the NPC respawn timers in Skywatch to 40 seconds, stymying the endless flood of monsters and effectively ending this particular instance of the loot cave phenomenon. However, the community has quickly identified new locations with a similar farming dynamic.

Bungie could continue to hotfix respawn timers, but in aggregate that might have the unintended effect of emptying out low-level patrol areas. They could prevent weak monsters from dropping legendary gear, but that might make much of their world obsolete to players past level 20. Ultimately, I think Bungie is already planning systemic changes in the right direction: making their existing end-game content more rewarding. If the strike & raid missions find an appropriate balance of difficulty, reward and fanfare, then players might stop hunting for a cave to shoot into.

→ No CommentsTags:  ·  · 

More Twitter Bots

Internet, Programming

Tweets by @EveryBookBot

Since I released @HoroscopeBot earlier this summer, I haven’t stopped thinking about Twitter bots as a creative medium. Corny “I could make a bot for that” ideas kept popping into my thoughts. After reading this appreciation of museum bots, I decided to try my hand at making something similar for a different catalogue.

This led to the creation of @EveryBookBot. Every hour, it takes a random word from Wordnik and tweets a book on that subject from the Google Books API. The goal is to mimic the serendipity of browsing a library or a friend’s bookshelves. Books cover such a delightfully broad range of topics, everything from crackle glass and Spanish fashion to concise philosophy and thumb wrestling. The more obscure subjects fascinate me; who loved this thing enough to write a book about it, and who was their audience?

Tweets by @EveryGameBot

Its sibling @EveryGameBot isn’t quite as diverse, but perhaps that’s to be expected from a younger medium. This bot tweets a random video game or board game every hour, drawing data from the Giant Bomb and Board Game Geek APIs. Highlights so far include a political game from 1894 and an obscure fighting game best remembered for its FF7 tie-in. Exploring old esoteric games feels particularly worthwhile in a culture that’s too often fixated on the new and popular.

On the technical side, both bots resize and tile the book/game covers using a JS ImageMagick library. The cover tiling is done to reach the 440×220 image size that Twitter prefers, though I rather like the aesthetic effect as well. I’m also using a simple PostgreSQL database (which Heroku conveniently provides) to ensure the same item doesn’t get tweeted twice. The source code for both bots is available on Github.

→ No CommentsTags:  ·  · 

Making @HoroscopeBot

Internet, Programming

Tweets by @HoroscopeBot

Last weekend, as a side project, I decided to create an oracle. Like most oracles he spouts nonsense, occasionally happening upon a cogent statement by random chance and serendipity. His name is @HoroscopeBot, and he takes the auspices of Twitter to post a semi-coherent prophecy every twenty minutes.

What inspired this unusual creation? Through another act of internet happenstance, I became acquainted with two prolific bot-makers: Darius Kazemi and Rob Dubbin. As I followed their various projects, I slowly became convinced that bots were more than a mere novelty. Their playfulness with language and meaning was strangely revealing. They were subversive in a world that is increasingly run by algorithms. They could also embrace the inherently unpredictable nature of automation and make it charming.

While ruminating on these bots, I conceived of a simple bot idea of my own. I decided that I needed to make it right away, and devoted an idle weekend to develop the minimum functionality. The idea was to to find tweets of the form “you will ______”. If I prepended two such statements with a zodiac sign, it would create a disjointed horoscope. For instance:

GEMINI ♊: You will come out on the banks of the Rio Grande, but you will have to build a jail.

LIBRA ♎: You will be my queen, but you will NEVER MAKE A FREE THROW IN YOUR LIFE.

SCORPIO ♏: You will understand it, but you will need tissues.

On the technical side, this involved communicating with the Twitter API using OAuth, parsing text with regular expressions, and finding a host that could re-run the logic at set time intervals automatically. Following an online tutorial, I began developing my bot in Google Apps Script.

I initially thought that grabbing tweets would be the most difficult technical hurdle, but the API was actually quite straightforward. The rub was that my application required manual reauthentication every few hours, which is a major annoyance for a program that’s defined by its ability to run 24/7. Twitter has a workaround for this; they will provide you with a single access token that will never expire. However, Google’s OAuth library would not allow me to simply provide it with a token; it wanted to do authentication the “right” way.

To make the bot fully independent, I had to port the logic to Node.js and deploy it on Heroku. This was not a smooth process (mostly due to the limitations of my git knowledge), but the twit library finally enabled me to connect to Twitter indefinitely with my access token. As of Sunday morning, @HoroscopeBot should regularly tweet new prognostications with no further intervention; you can check out the source code on GitHub.

In an interview with the Boston Globe, Darius says he was inspired by Ian Bogost’s idea that, in lieu of writing, objects can embody philosophy. In that context, I’ve thought about what sort of viewpoint my bot is advancing. Maybe it demonstrates the incompleteness of written language. Sentence fragments are fungible, and simple juxtaposition can create unintended meaning; context is always important. Alternately, perhaps it celebrates second-person aspirations. Somebody is saying “you will”, will you?

→ No CommentsTags:  ·  · 

© 2007-2015 Matthew Gallant, hosted by A Small Orange, powered by Wordpress.