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:

Tweets by @RandomChessBot

@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.)

Tweets by @SeeHearPartyBot

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.

Tweets by @GameOfLifeBot

@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?

Tweets by @VerifiedBioBot

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.

Tweets by @TinyCrossword

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:  ·  ·  · 

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:  ·  · 

Solo Queue: An Exercise in Serenity

Programming, Video Games

This weekend I committed to finishing a small Twine game I’ve been dabbling with intermittently for the last year. It may seem a little esoteric (and rather silly) if you’re unfamiliar with the game genre being parodied, but hopefully it’ll still convey the general idea.

You can play it directly in your browser by clicking the title below:

Solo Queue: An Exercise in Serenity

Solo Queue is inspired by Dan Bruno’s Time for some Fire Emblem and Alex Austin’s Bioshoot Infinite + 1. I was intrigued by the notion of abstracting a game’s core mechanics into Twine as a form of critique. I wanted to apply the same approach to the lords management game (a.k.a. MOBA) I play most regularly: League of Legends.

While I was fiddling with Twine, I was also working (and eventually had some success) at climbing the season 3 ranked ladder in solo queue. There is a certain inherent insanity in attempting teamwork with four complete strangers. To quote Reservoir Dogs:

Mr. Pink: Why can’t we pick our own colours?

Joe: No way, no way. Tried it once, doesn’t work. You got four guys all fighting over who’s gonna be Mr. Black, but they don’t know each other, so nobody wants to back down. No way. I pick. You’re Mr. Pink.

Succeeding in solo queue requires diplomacy, flexibility and ego management. Ultimately, it’s a lesson in serenity; you must accept that you are going to lose many games regardless of your personal performance or skill.

Solo Queue in Twine

As I’ve indicated previously, I had some troubles working with Twine. In fact, halfway through development I moved the passages to a plain text file and began compiling them directly with twee. I also wanted to avoid mixing JavaScript code with story content, so I stored the macros in separate files and wrote a few quick Perl scripts to append them together at build time. The workflow worked quite well once I’d set all that up; I especially enjoyed being able to easily import Leon Arnott’s excellent Twine macros.

It felt great to work on a hobby game again, though I’d like to attempt something with more systemic mechanics for my next side project. In the meantime, I hope you enjoy my preposterous little game, and to all the League players: best of luck in season 4!

→ 1 CommentTags:  ·  · 

Twine Troubles

Programming

Photo by Daniel Schwen

The interactive fiction platform Twine has been around for many years, but recently it’s been at the centre of the DIY game creating movement. Rise of the Videogame Zinesters heralds it as an accessible development tool for those without programming experience. New voices are joining the game-making world, and the variety of Twine games is truly remarkable: personal games, satirical games, Kafkaesque games, sexual games, and many more.

Inspired by the creativity of this new wave of game makers, I decided to work on a small Twine game as a side project. I read a few tutorials, downloaded the application, and began assembling a story. Unfortunately, I started encountering minor hindrances much sooner than expected. I was digging through forums and documentation to implement functionality that I thought would be trivial. Disheartened, I frequently had to resort to kludgy workarounds.

Here are my four biggest frustrations with Twine:

No Nested Logic

Twine has built-in syntax for linking passages, displaying text conditionally and getting/setting variables. However, the syntax does not allow any of these to be nested. You can’t display a variable inside a link or a conditional statement. You also can’t embed any html inside a link, which makes image links difficult.

// Can’t print a variable in a link
[[Hello there <<print $name>>|Say Hello]]

// Can’t conditionally print a variable
<<if $name eq "Bob">>Is <<print $husband>> feeling better?<<endif>>

// Can’t embed an image in a link
[[<html><img src=”foo.jpg” /></html>|Link]]

The workaround is to write your own html in these cases, instead of using the built-in Twine syntax. You can access the Twine variables and link to passages using JavaScript, though that has its own headaches (explained in detail below.)

Verbose Macros

Twine allows you to write custom JavaScript macros, which is great! The process for doing so, however, is a tad obfuscated and verbose. To make a macro: create a new passage, add the tag “script”, then write your logic in a function with the following template:

macros['randomnumber'] = {
    handler: function(place, macroName, params, parser) {
	insertText(place, Math.random());
    },
  };

That’s the bare minimum script for inserting a random number. Here’s a fancy version with all the bells and whistles:

try {
  version.extensions['randomnumber'] = { major:1, minor:0, revision:0 };
  macros['randomnumber'] = {
    handler: function(place, macroName, params, parser) {
	if (params[0] === undefined) params[0] = 0;
	if (params[1] === undefined) params[1] = 1;
	var n = Math.round(Math.random()*params[1] + params[0]);
	insertText(place, n);
    },
  };
} catch(e) {
  throwError(place,"randomnumber error: "+e.message); 
}

None of it is egregiously verbose, but boilerplate phrases like “handler function place macroName params parser” are daunting. Twine is a great tool for first-time game makers, it would be nice if writing macros was equally approachable.

I also wish it were possible to import script functions from external files. That would allow authors to share and reuse modular components. A library of common functions would be a boon to those without the technical knowledge to write their own JavaScript. Dan Cox has a clever macro for loading external JavaScript libraries, which I’d love to see integrated natively.

File Format

Twine is a graphical interface wrapper for a simple plaintext format (called twee). However, the application saves stories in a .tws file, which is just a Python pickle serialization. Since this format is not human readable, it discourages the use of source control. Why bother tracking your changes when you can’t understand the incremental differences?

Thankfully, there’s an easy built-in way to get around this. In the Twine menu, call File > Export Source Code to export your story to a plaintext twee file. You can even modify that file in a text editor and reimport it back into Twine (though you’ll lose some of your previous passage arrangement).

Weak Documentation

There is some documentation for both Twine and twee. The former covers the basics and the latter alphabetically lists available functions (assuming robust JavaScript knowledge); neither is terribly useful for learning to write macros. I found the answers to my questions scattered across the TweeCode google group, Porpentine’s resource compilation and Dan Cox’s macro tutorials. Here are a few useful tricks I had to figure out the hard way:

Firstly, if you want to link to a passage (named “foo”) from embedded html (e.g. for an image map) use <html><a href="#" onclick="javascript:state.display('foo', this); return false;"> foo </a></html>. (If you neglect to return false, it’ll work on Chrome but not Firefox.)

Secondly, if you set a variable in Twine syntax using <<set $foo = true>>, you can access it from within JavaScript macros with state.history[0].variables["foo"]. You can use this to get around some of the nested logic issues I mentioned earlier.

Finally, a minor idiosyncrasy: Twine does not allow links back to the “Start” passage. Many authors get around this limitation by making a new first passage and displaying it in “Start” with <<display ActualStart>>.

Despite my criticisms, I still think Twine is a valuable and important platform. Fixing certain small issues would simply improve what the tool already does well: provide a accessible way for everyone to make personally meaningful games. Twine is free and open source with a passionate community, so I’m certain it’ll continue to improve and grow.

→ 5 CommentsTags:  ·  · 

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