mary rose cook

The rules of Ninja, as I learnt them last night at the Bocoup offices

1. Players stand in a circle, each an arm’s length apart from their neighbours.

2. Someone shouts, “One! Two! Three! Ninja!”

3. On, “Ninja!”, the players adopt a ninja-like pose and remain still.

4. The person who counted everyone in now makes their first move. Their aim is to use their hand to touch the hand of another player, thus killing them. The player’s move must be made in one smooth motion. They may only take one a maximum of one step. The player being attacked may move their upper body in defence.

5. The next player then makes their move, and so on around the circle.

A video of one of the games we played at the Bocoup offices:


Scruffy Slut

About a week ago, Kanen Flowers interviewed me on his show, Scruffy Thinking. I am very honoured. We talked about my latest record, using emacs, Pistol Slut, Kanen’s alien snuff movie, BBEdit, dressing like a teenaged boy and landing in Bangkok for a two day layover and only finally leaving a year and a half later. To listen, go to the Scruffy Thinking podcast on iTunes. Here is a post about the show on the Scruffy Thinking site.


The Setup

I got interviewed on The Setup and, in doing so, wrote a love letter to emacs.


Video of my talk at JSConf US on Fakery, artificial intelligence, collision detection and falling in love in Pistol Slut, a 2D platform shooter


Download 10997

A few months ago, I released my new record, 10997. I put it out as a CD-R and gave copies to friends and to people who emailed me. I was reluctant to make it downloadable because the lyrics are about stuff that was current affairs. Now, however, that’s not really true, so stream and download away.


Machine.js

The first version of the artificial intelligence code that controlled the enemies in Pistol Slut, my 2D platform shooter, was a nightmare thicket of if statements. Fortunately, someone told me about behaviour trees, and, after reading half of an excellent article about their implementation in Halo 2, I rewrote the Pistol Slut AI code as a hierarchical state machine. To do this, I made a little JavaScript library called Machine.js that implemented a generic behaviour tree. This code is open source, like all of the code I write in my spare time, but, today, I broke it out into its own library and released it as a separate project. This should make it easier for other people to reuse.

Go to the Machine.js home page to get the code and read a tutorial.

And, in case you are interested, here is the entire behaviour tree for the enemies in Pistol Slut:


The slides from my talk at JSConf US: Fakery, artificial intelligence, collision detection and falling in love in Pistol Slut, a 2D platform shooter in JavaScript





























































































JSConf US 2011

I’ll be speaking at JSConf in Portland on 2nd May. I’m very excited. I will talk about Pistol Slut. Specifically: fakery, artificial intelligence, collision detection and falling in love.


10997

I have finished my new record. It has four songs: Argentina, Somaliland, Barcelona and Nicaragua. I recorded it on my phone in the kitchen of my apartment in Berlin. Email me your address and I’ll send you a copy in the post.


The slides from my talk on Pistol Slut

Update: I gave a newer version of this talk at JSConf US 2011. See the slides.


I’m giving a talk about Pistol Slut at the Berlin JavaScript group

I’ll be speaking about Pistol Slut at the Berlin JavaScript group at 7pm on 17th February 2011. You can find out more on the Lanyrd event page.


A Prophet, a great film


2D collision detection in Pistol Slut

For the last six months, I’ve been writing Pistol Slut, a 2D shoot-em-up in JavaScript. In this article, I’ll talk about how I solved some of the nastier problems with detecting collisions between 2D objects, specifically: bullets, grenades, exploding barrels, buildings and people.

You might find it helpful to play Pistol Slut before you read on, so you have a context for the things I talk about.

I will not be talking about per-pixel collision detection. And I will only be talking about objects whose shapes can be roughly approximated to a rectangle.

Most of the examples in this article will be conducted in pseudo-code. If you want to see the code I actually used, go and look at the repository for Pistol Slut. Both it, and the framework it is based on, The Render Engine, are open source under the MIT license. This means you can take the code and use it in any project, commercial or non-commercial, open source or not.

This article will begin with the general approach to collision detection. It will then go into special cases that solve some of the trickier problems.

Grids

Imagine the whole game world split up by a grid. If two objects are in the same square of the grid, we assume they are colliding, like these two red squares.

Whereas, these two red squares are not colliding:

So, to detect whether a particular object is colliding with another one in our simple little world, we can use this code:

What if the world looks like this?

Uh-oh.

An object might exist in more than one grid square. How about we get the coordinates of all four corners of each object and add the object to the grid square containers into which the coordinates of those corners fall? No, that’s not going to fly, either, because the world might look like this:

There are two solutions. Solution one, use bounding boxes, the subject of the next section. But we don’t really want to do that, because the grid is supposed to be a super-quick triage that dramatically cuts down the number of collisions we have to test further. Solution two, assume that an object will never be bigger than a grid square and, therefore, we can just add it to the grid square container into which its top left corner falls, and the containers of the eight surrounding squares. To make this happen, we can modify the second block in the previous code, giving us:

One last thing: what happens if an object moves? It might have moved to a new grid square. It’s no big deal:

Bounding boxes

We can now get a list of all the objects that a particular object is colliding with. But that’s kind of lies, isn’t it? Though the two red squares in the first diagram are occupying the same grid square, they aren’t actually colliding. Grid square co-habitation is only the first step. The next is to find out whether an object is actually overlapping another object, like these two love-birds:

We do this with bounding boxes. A bounding box is a square that is as tight a fit as possible around the actual boundaries of an object. A bounding box is defined by the x and y coordinates of its top left corner and the x and y coordinates of its bottom right corner. If two objects’ bounding boxes overlap, those two objects are colliding. To calculate if two bounding boxes overlap, we run four tests that would confirm the boxes *don’t* overlap. If all four tests come back false, the boxes are overlapping:

To get all the objects that a particular object is colliding with:

Putting it all together

The object’s reaction may depend on what type of object it has collided with. Its decision about whether it wants to hear about more objects in its grid square in this tick might depend on whether its reaction involved it being destroyed. If it is destroyed, it will probably remove itself permanently from the pool of objects in the grid.

Special cases

This is the tougher stuff. I’ll talk about how to deal with fast-moving objects, objects that can stand on top of others, objects that can push others and objects that bounce.

The root cause of most of the difficulties is the fact that objects can move several pixels per tick. Thus, you do not always hear about collisions until after one object is well inside another. Thus, it’s sometimes hard to tell at what coordinates the impact occurred. I’ll take some objects from Pistol Slut, explain the difficulties with each object, and the solutions.

Bullets

Problem one: in a tick, bullets can pass right through objects they should be colliding with. Solution: make sure they can’t ever move at a pixel speed higher than your narrowest object. You could do this by taking care to build objects that aren’t too narrow, or put a speed limit on bullets that is based on the width of your narrowest object.

Problem two: it’s hard to tell at what coordinates a bullet entered a dustbin, which makes it difficult to show the point of impact with a shower of sparks. Solution: extrapolate back through time. I have no idea what this technique is really called.

Here is a red dustbin with a red bullet being shot at it. It passes through positions A, B and C in that order.

Unfortunately, ticks only occur when the bullet is at positions A and C. Therefore, with the system outlined above, the bullet won’t know about a collision until it reaches position C. That will be fine for destroying the bullet to represent the fact that it has hit the dustbin, but it won’t be so great for doing the beautiful shower of sparks. If we drew those sparks at point C, the location of the bullet when we detected the collision, they would look like this:

Lame.

We need to find position B. That way, the sparks will originate from the point of impact. As a bonus, I will show you how to make the sparks go in the right direction.

For the first part, draw an imaginary green line between position C and position A. That is, a line between where the bullet is now and where the bullet was in the previous tick. Then, draw four more imaginary purple lines, one along each side of the bounding box of the dustbin.

The move is to find out which bounding box line the C to A line intersects, and where. Here are two JavaScript functions; the first tells you if a line between p1 and p2 and a line between p3 and p4 are intersecting and the second tells you where.

So, with the power of maths in our hands, we can now figure out where position B is:

And, thus, emit the shower of sparks from that point.

But in which rough direction should the sparks go? Ack. Start crying: here comes some more maths.

reverseAngle() is the key function, here. It gets the normal to the side of the dustbin that the bullet hit. That is, it gets the outward-facing line that is perpendicular. It gets the angle between the normal and the bullet’s vector and then spins that angle around to adjust it to the direction appropriate for the side that was hit. The result is the angle the sparks should go along.

Grenades

Problem one: grenades bounce. Solution: use the code from the Bullets section to get the point of impact of the grenade and then reflect the angle of impact and send the grenade off in this new direction. And maybe reduce the grenade’s velocity a little to account for friction and the fact that grenades aren’t exactly like super balls when it comes to bouncing. Easy.

Problem two: solution one was a bit of a lie. The reflect direction stuff we used for bullets will still work great with grenades, but the stuff with using the grenade’s current and previous positions to get its trajectory and, thus, where it hit the dustbin, can be problematic. It’ll work most of the time, but not all. I’ll explain why.

When we drew the imaginary line between the current and previous positions of the bullet, we drew it between the top right hand corners of the two positions. This is fine, because the bullet actually IS only a single point. It’s drawn as a single pixel. But grenades are bigger than that. So, something like this might happen:

The first time we hear about a collision with the red dustbin will be when the red grenade is at position A. The next tick will find the grenade at position C. But there’s no position B. Why? Because we will draw a line between the top lefts of the grenade at positions A and C, and that line will not intersect with any of the sides of the red dustbin. Thus, we will not get a point of impact and, thus, we won’t know where to bounce the grenade from.

Why not draw lines between every corner of the previous and next positions? That is, top left to top left, top right to top right and so forth. Good thinking, clever-clogs. But what about this scenario?

Do you see? Though the red grenade is colliding with the red dustbin at both positions A and C, a line drawn from the top left of position A to the top left of position C would not intersect the edge of the dustbin. The same goes for a line from top right to top right, bottom left to bottom left and bottom right to bottom right.

The solution has two cases. In the first case, at a particular tick, the red grenade is intersecting the side of the red dustbin:

In this case, the code to get the angle to bounce the grenade is straightforward:

To determine whether a line intersects a box, make a rectangle of the line and then see if that rectangle overlaps the box rectangle. To make a rectangle from a horizontal or vertical line between p1 and p2:

In the second case, the red grenade is already fully inside the dustbin:

To deal with this, we use a technique called sweeping. The idea is to move the grenade back along its trajectory in small increments, testing at each position to see if it is overlapping any of the sides of the dustbin. Like this:

The initial collision is detected when the grenade is at position A. We then sweep its position back incrementally to positions B, C and D, testing to see if it collides with any of the edges of the red dustbin. We finally get a hit at position E.

To handle both this case and the previous case, we can write this code:

People

What is special about people? They can bump into and stand on top of things. To handle these scenarios, we can write this code:

And to figure out whether the girl is falling or rising or walking through the dustbin, we can write this code:

Exploding barrels

Exploding barrels are not so notable for their explodeyness as for the fact that they can be pushed. Using the code we are already using for the girl, we can handle this:

Artificial intelligence

That’s it for the collision detection in Pistol Slut. Well done. My next article will be about artificial intelligence with state machines.


Next gig


I wrote a quiz for my family. This is the film round. Name the actors pictured and the title.


Pistol Slut third demo

It’s starting to turn into a game. Last night, as I played through the level, I felt a first jolt of fun. I’ve made the frame much wider to allow the pitched battles that I think are going to be the core of the game. I’ve added mortars, floating Chinese lanterns and four planes of parallax scrolling. I added and then removed cycling of the colour of the sky from dark to light to dark. The police don’t accidentally shoot each other any more, and they throw grenades.

It is so fun to work on a game. It’s a completely different type of programming from making a website. There are far more interactions between different elements. It is a machine with parts working in concert, whereas a website is a landscape with disparate lanes leading away from each other. Tom Klein Peter said this of building Audiogalaxy:

In fact, almost everything about the scale of the software fascinated me. I found that a system with hundreds of thousands of clients and thousands of events per seconds behaved like a physical machine built out of springs and weights. If one server process stalled for a moment, effects could ripple throughout the cluster. Sometimes, it seemed like there were physical oscillations – huge bursts of traffic would cause everything to slow down and back off, and then things would recover enough to trigger another burst of load. I had never even imagined that these sorts of problems existed in the software world and I found myself wishing I had taken control theory more seriously in college.

I am constantly generalising code so it can be shared: the code that moves objects around, the code for operating a weapon, the code for firing different types of ordinance, the code for different types of particle and particle effects. And I am constantly fighting to improve performance. Usually, when I add something new, the game becomes laggy. I then work on optimisation for a while until I get performance reasonable again. Sometimes, the optimisations involve re-writing the code to make it more efficient – for example, I rewrote the code that triggers events in the level to make the checks for trigger trips far quicker – this requires being clever. Other times, the optimisations come from finding something that is computationally expensive and removing it – for example, I chopped up the graphic for the front-most parallax level into smaller parts to stop the engine wasting time drawing the great tracts of empty space – this requires sacrificing code elegance.


Pistol Slut second demo

This is the second demo of Pistol Slut, the 2D, shoot-em-up platformer I’m writing in JavaScript. You can play it at pistolslut.com.

The game now has a mortal enemy who can shoot, take cover and be suppressed by incoming fire. So, Pistol Slut can keep the enemy pinned down as she advances, then unleash a hail of bullets for the kill. Pistol Slut is now mortal and can crouch, throw grenades and, the faster she shoots, the wilder her shots go. After expending her magazine, she must reload.

Pistol Slut has paid a visit to the Sluts With Guns free shop and got an M9, Mac-10 and SPAS shotgun.


It’s Flashbeagle, Charlie Brown

I used to watch this when I was a child. I think my God mother gave it to me on video. The programme comprises four songs performed by characters from Peanuts. A few years ago, my friend, Dave, and I discovered a mutual appreciation. He even has a copy on DVD. We recorded a cover of Lucy Says in the last afternoon before I moved from Leeds to London.


Experimanntag

Last Monday, I did the first Experimanntag for my colleagues at Ableton. I showed a film by Michael Mann and then we went to Experimontag, an experimental music club in Berlin. Next week: The Insider.


Hurray for the Riff Raff


You Died on 12th May 2009

I’ve released my solo band’s new record on CD. It has six songs and you can listen to and download it here. Or, email me your address and I’ll send you a CD in the post.


Pistol Slut: some details about her

Pistol Slut is a 2D side-scrolling shoot-em-up platformer that I am writing in JavaScript. The game is displayed by a Canvas element. It works in Google Chrome, Safari and Firefox in theory, but not Internet Explorer.

Demo

The most recent vaguely stable version will always be available at pistolslut.com.

Framework

I use The Render Engine by Brett Fattori. It’s a fabulous framework that handles the basics of rendering graphics and sprites to the Canvas element, moving objects, collision detection, animation and level loading.

Code

The Pistol Slut code is open source and available on GitHub. It would be a good reference for anyone who wants to learn about advanced capabilities of The Render Engine that aren’t covered in the demos that come with the framework: animated sprites, level object loading and enemies.

Features so far

A scrolling background, running, jumping, shooting, muzzle flash, bullet ricochets, enemies, snow, animated sprites, scrolling Orwellian signs.


Pistol Slut

A demo of the pre-alpha version of my JavaScript game, Pistol Slut.


» I've just read The Insurrectional Project [PDF], a zine comprising discussions of different aspects of anarchism. I disagreed with it as much as I agreed with it, but it has set off lots of little explosions in my head.


» A very fucking cool post from Randall Munroe of xkcd about the intersection between sex, gender and categorisation.


How I made Street Hoarding, a Node.js and Redis application, or, a super simple explanation of asynchronicity, event loops, non-blocking IO, JavaScript, Comet and Node

Second update: thanks to James Coglan again, I have modified the code. Now, the client message requests are held open until there is a new message to return, thus reducing the load on the server.

Update: Thanks to James Coglan for providing some lovely technical corrections to this article.

Go to the Street Hoarding homepage and you will see a message in big letters. If you wish, you can type another message in the text box at the bottom of the page, press return, and see it take the place of the old message. Anyone else on the site at that moment will see your words within a few hundredths of a second. It’s kind of like a community pin-up board, or some hoarding on a building site, or a promiscuous IM client with a very short memory.

Some of the key parts of the code were taken from Ryan Dahl’s demo chat app for Node.js.

My aim with this article is to explain how everything works to someone who is like I was before I wrote Street Hoarding: hazy about asynchronicity, event loops, non-blocking IO, JavaScript and Node.js.

There are two elements: the client and the server.

The client

This is an HTML page that lays out the main message and the text box. It is also the JavaScript that runs on the user’s browser. The JavaScript has two key functions.

longPoll() runs the whole time the user has the webpage open. It takes some data. If this data is null, it is ignored. If it is not null and has a message component, that message is displayed on the webpage through a jQuery update to the message div. Either way, an XMLHttpRequest request is then made with jQuery to the /latest_message url on the server. This request takes some time, but it is asynchronous. That is very important. When longPoll() is run, the data is processed, the URL request is made and, then, the execution of longPoll() continues past the $.ajax() call, and control is passed back to the computer processor so it can carry on doing other work. When a success response comes back, the success function inside the $.ajax() function is run. This pauses for a moment, then calls longPoll() again, passing it the data that the server responded with. Next time through, the message inside this data will be written to the HTML page and the user will see it.

tryToSendMessage() is called when the user submits a new message via the text field on the HTML page. It first sends an (asynchronous, as always) request to the server to ask it whether the message the user entered has ever been said before. If it has, it just tells the user they aren’t being original and finishes. Otherwise, it sends an (asynchronous) request to the /send_message URL, passing the user’s message as a parameter, thus telling the server to save the message.

There are some improvements that could be made to this code. First, when the message is sent to the server, it does not get updated in the user’s browser immediately. That will have to wait until the longPoll() function gets its next response from the server. Second, the user has no idea whether the /send_message request was successful until longPoll() updates the webpage. Third, the message is actually sent twice. The uniqueness check request and send message request could have been combined into a single /send_message request that had the server respond with either an indication of success or a message saying that the message was not unique.

I keep on saying the word asynchronous. Everyone who talks about Node.js goes on about asynchronous execution and this other thing, non-blocking input and output (IO). What is crazy is that we haven’t even got to the Node.js stuff, yet. This is all browser magic that we’ve had for the last whatever years.

So, let’s go back a bit.

When a request goes from the client to the server – either asking for the latest message or sending a new message – the computer processor doesn’t hang around waiting for a response. Instead, it moves on and deals with other tasks. The processor returns its attention to the request when the response comes in. Thus, the input and output are non-blocking. Which is to say, waiting for data to arrive or be sent does not hold the processor up from its other tasks. From this, we get asynchronicity – lines of code can get executed out of order. If there is a pause whilst a function waits for something to happen and that something does not require the computer’s processor, other work can be done in the meantime.

How does this work?

There is this thing called an event loop and every browser has one. This is a function that just goes around and around, taking note of things that happen like a woman alone in a house at night straining to hear every floorboard creak and passerby’s creep. Code, like jQuery, that is running is the browser, can register its interest in different types of event. So, when the $.ajax() jQuery function is called in longPoll(), it sends out the request and then tells the event loop it would be very interested in hearing about any HTTP responses that come back from the server. The event loop eventually gets the response and passes it to jQuery which looks at the response to see if the request was a success, and then runs one of the two functions that we defined in longPoll().

This is where JavaScript plays its part.  JavaScript has – and you may have heard this term before – first class functions. These confer several abilities, but the one we care about is that functions can be passed as arguments.  In longPoll(), functions are passed as the fifth and sixth properties of the $.ajax() call. The first is to be run in the case of a response that indicates an error, the second in the case of a successful response.

Now, back to the request from our client code.  Using a browser means we are in an event loop. Making an HTTP request means we have time when the processor is not being used. Using jQuery means that control is handed back to the browser after a request is sent. The browser regaining control means we have non-blocking IO. Non-blocking IO means that the event loop continues to run whilst it awaits a response. The event loop continuing to run means that other tasks can be dealt with in the mean time.

That deals with the wonders of non-blocking IO and asynchronicity on the client. If we already have all that stuff, I ask, Why is Node.js so special? and I answer, Because this is now easy to do on the server, too.

The server

There is some crazy fucking shit going on in the first line. It uses fu, an imported piece of JavaScript code that acts as a mini router. When you pass a url and a function to fu.get(), you are saying: when the Node.js server gets a request that was sent to this URL, run this function.

A digression on how the router works that explains some things about JavaScript and the Street Hoarding code but that it’s not really necessary to read to get the main points of this article

fu.get() takes a URL and a function and adds the function to a hash, keyed with the URL. fu.listen() starts the server defined by the server variable and makes it listen to events coming to the passed host (probably localhost) on the passed port. We’ve eaten our way around the jam filling, so it’s time to get sticky fingers.

createServer(), a Node.js function, is called with an anonymous function that takes a request and response, and the resulting server object is assigned to the server variable. That anonymous function gets the URL on the passed request object, req, and looks in getMap to find the corresponding function to run. For example, in the latest message code defined above, the url is /latest_message and the function is the rest of the code snippet.

We now meet a second special feature of JavaScript: prototyping. The passed response object, res, has two new methods added to it on the fly: simpleText() and simpleJSON(). The methods themselves are not that interesting – they just create a string to return to the client as a response to its request – it is the fact that they are stuck on the res object without such as a by your leave that I just know is making your head explode.

Finally, the handler function in getMap that corresponded to the requested url is called with the request and the super-charged-with-new-functions response.

Latest message

So, the function passed to fu.get() extracts the since parameter that the client sent with the request. This indicates when the client last received a user message from the server. If the server has received a message from a user since then, sendLatestMessageToClient() is called.

sendLatestMessageToClient() creates a new Redis client. It calls redisClient.stream.addListener() to connect the Redis client to the Redis server, passing a function as the second argument. Note the asynchronicity. The Redis library does not hang around waiting while the Redis client connects to the Redis server. Instead, behind the scenes, it passes control back to the server event loop which, at some point in the future, gets an I’ve Finished My Work And My Name Is The Redis Client Connection Function event which then calls the function passed as the second argument.

This function calls redisClient.lindex() which retrieves the first item in the messages list in the database. Three arguments are passed: the key of the messages list, a 0 to indicate the first item in the list, and yet another callback function. redisClient.lindex() retrieves the first message (did you notice the auxiliary bout of asynchronicity?), and the callback is run which closes the Redis client and runs the simpleJSON() function to send the message back to the client. (Those of us who read the digression are like fully in a special secret club what knows how totally mind-fucking it is that the res object has a simpleJSON() function hanging around on it; those who did not read the digression will keep their heads fuck-free.)

New message

The function passed to fu.get() extracts the message from the request and calls storeMessage(), passing the message and yet another function to call back later.

storeMessage() goes through the familiar routine of creating a Redis client, requesting a connection to the Redis server, calling a Redis function (redisClient.lpush, this time), closing the Redis client and calling back the function passed as the second argument which:

Wait, stop a second. Do you remember how I rather trailed off five paragraphs ago when I wrote, “If the server has received a message from a user since then, sendLatestMessageToClient() is called”? By which I mean, I didn’t say what happened if the server had not received a new message since the last message was sent to the user. Let’s have a look.

Right. Latest message requests that would normally be answered with the message that the client is already displaying are held open. I know that was a long sentence, and this is a long article, and you are tired, but I hope that those last two words didn’t slip by you. Held open. A response is not sent immediately. Instead, a new item is pushed onto the messageRequests array: a hash of the res object and the sendLatestMessageToClient() function.

So, back to the /send_message code to see how it deals with the held message requests. The code extracts the user’s message, stores it and sends a success response back to the client. For each message request that has been pushed onto messageRequests, sendLatestMessageToClient() is called. This sends the latest message (probably the one received a few lines ago) back to the client, thus ending the request. This is Comet: the client sends a request and no response is sent until there is something useful to send, thus the request is held open.

Ryan Dahl did two really cool things. First, he wrote a library that lets you code an event-driven server in JavaScript. However, this was not new. Second, and more importantly, he wrote the core libraries so that they are non-blocking. The problem with other event-driven programming libraries is that you can’t be sure whether the auxiliary libraries you want to use are non-blocking. If they are, you will stall your event loop and it will stop dealing with incoming events and everything will fall apart.

So, from the re-written libraries, we get non-blocking IO, which allows an event loop. The event loop allows the server to run in a single process. A single process means low memory usage.


“Maybe pretend that you’re in the grocery store having to defend your queer body.”


Freeing disk space on your Linux server

The websites that I host on Slicehost, Playmary and Street Hoarding, keep crashing because my slice keeps running out of disk space.

To find out where disk space is being used:

1. Get to the root of your machine by running cd /
2. Run sudo du -h --max-depth=1
3. Note which directories are using a lot of disk space.
4. cd into one of the big directories.
5. Run ls -l to see which files are using a lot of space. Delete any you don’t need.
6. Repeat steps 2 to 5.


Fourth EP

I finished the new mary rose cook music record months ago, but, since moving to Berlin, I haven’t got around to photocopying the inlays and burning the CDs and doing the stapling. Soon.

I wrote the note in the photograph and pinned it to my bedroom wall when I came back to London, two months after having a cardiac arrest.


Say you want an insurrection


oem download software mac

Adobe Dreamweaver CS5 Student and Teacher Edition download now staad oem downloading publisher 2007 oem oem software installshield download digital jacket 4.0

purchasing the software package oracle crystallball

download now Adobe Creative Suite 5 Master Collection monyog pricing adobe elearning suite 1 download download now buy windows 2000 sp4 erwin data modeler buy

pro tools m powered 7.4 download

buy online Lynda Excel: VBA in Depth cheap microsoft software cheap software coade caesar discount spyhunter cheapest buy windows vistaa

microsoft-cheap discount software for you

cheapest Lynda Photoshop CS4 for Photographers: Desktop Printing Techniques buy office 2008 mac presto pagemanager 8 buy online winx dvd ripper platinum cs3 for mac purchase and download

autocad 2005 for sale

Microsoft Office Home and Business 2010 [32 Bit] order adobe contribute serious magic ultra 2 download order online cheap windows vista adobe illustrator cs4

autocad oem

buy cheap Adobe Dreamweaver CS5 for Mac adobe mac autotune 5 cheapest sibelius 5 download cheapest cadpipe commercial pipe

cheap software downloads oem

oem Bigasoft ASF Converter download cheap software adobe creative suite 5 master collection oem buy cheap cheap reverb rtas oem lotus organizer 6.0 download

cheap software coade caesar

Lynda ActionScript 3.0 in Flex Builder Essential Training cheapest buy sounddiver win cheapest downloadable oem of photoshop cs3 buy cheap cinema 4d adobe indesign cs4 mac cheap

farstone virtual hard drive pro

buy online Symantec Norton 360 Version 3.0 Premier Edition acrobat 7 mac software sales oem buy anydvd hd cheap purchase adobe indesign for mac

cheapest adobe acrobat mac

Lynda ActionScript 3.0 in Flex Builder Essential Training download online buy windows 7 download download microsoft frontpage 2003 download now where can i get microsoft office 2007 cheap software retailer discount

toonboom storyboard pro oem

Adobe Flash Catalyst CS5.5 order download adobe acrobat 7 baseline software order online virtual pc 7 for mac download full download microsoft picture it photo editing software

cheap auto tune download

oem UltraEdit 16 buy visio professional 2007 keyscrambler discount oem download microsoft publisher 2007 academic download cheap antares autotune

cheap onspeed

Joboshare PSP Video Converter download online omnigraffle 4 glow-n-sparkle order online buy cheep soft cheep oem software

download microsoft publisher 2003

Lynda Flash Builder 4 and Flex 4 New Features buy online cheap software downloads oem software primavera download now ecopy software price cheap software download microsoft windows

statistica for sale

Adobe Contribute CS5 Student and Teacher Edition [MAC] buy online oem software for mac cheap soft oem photoframe.2.5 fo2pix artmasterpro v1 2

project 2003

download now Lynda Illustrator CS4 One-on-One: Fundamentals programs 3d max 8 csi safe 12 oem download cheap download software oem mac

oem microsoft office 2000 download

download now FileMaker Pro 10 Advanced for Mac buy cinema 4d buy adobe audition buy cheap oem mac and windows software adobe cs4 mac cheap

willmaker 2009 download

buy online Lynda Photoshop CS4 One-on-One: Mastery buy microsoft office visio professional 2007 discount software autocad 2008 download online staad pro cost adobe acrobat 7 mac

adobe cs4 master retail

Autopano Giga [MAC] order online cheap netnanny oem mcafee downloand buy cheap microsoft picture it! photo premium 9.0 adobe oem software download

buy microsoft office online mac

buy cheap Bibble 5 audio creator 1.5 purchase office publisher 2007 download download online autodesk impression price visual basic 6 academic pricing

download ecopy

download online Bigasoft ASF Converter cheap graphpad prism aiseesoft dvd ripper download now roboform pro sale download office 2008 mac

buy avira antivirus online

order Adobe Dreamweaver CS5.5 cheap ipod transfer software discount software online oem oem adobe elearning suie cs4 mac software download

ms office 2003 professional download

ACDSee Pro [MAC] download online ispy lan monitor cheap microsoft download order sibelius five download oem downloadable software windows xp

buy microsoft virtual pc 7 for mac

order online Intuit QuickBooks Enterprise Solutions 11 buying cheap softwares oem soft downlaod download now lotus organizer 6.0 price software purchase cheap

pagemaker oem

discount Adobe Contribute CS5 Student and Teacher Edition [MAC] elite rhvac software adobe illustrator 10 software buy online oem download software mac download 2003 microsoft publisher full version

cheapoemsoftware

Adobe Creative Suite 5.5 Production Premium cheapest arcgis desktop oem review oem software store mac buy online ecopy desktop download best price for microsoft communicator

ableton 7 mac software oem

order online Lynda Illustrator CS4 One-on-One: Fundamentals cheap photoshop dreamweaver download microsoft photodraw version 2.0 to buy buy copy commander 9 adobe acrobat pro mac download

cheap abobe downloads

buy cheap Adobe Dreamweaver CS5 Student and Teacher Edition [MAC] microsoft visio pro 2003 download photoshop cs4 oem uk download buy microsoft picture it numark cue professional dj software oem

mldownloader 7.1.0.9

discount Adobe Creative Suite 5 Master Collection visio standard professional cheapest corel software download now download indesign cs3 mac softsalesterritory

fototime

Adobe Dreamweaver CS5.5 order 123 bulk email direct sender in oem stores adobe photoshop cs4 extended oem download windows 7 ultimate oem ihs questor

steinberg my mp3 pro 5.0

download now Lynda Photoshop CS4 for Photographers: Desktop Printing Techniques microsoft office 2008 mac oem adobe cs4 cheapest erwin data modeler buy where to buy cheap bulletproof ftp client

cheap soft

Microsoft Publisher 2010 buy online adobe best price visio standard professional order online adobe web premium discount purchase of microsoft picture it 9 -- where

buy sibelius

Adobe Flash Catalyst CS5.5 discount buy sparx systems enterprise arcitect purchase dreamweaver for cheap free download download now ulead photo explorer 8.5 featurecam cheap

autodesk architectural studio 3.1

DropDMG [MAC] buy online oem photoshop cs4 german photoshop 7 oem software download adobe acrobat 9 pro cheap arcsoft total media 3 platnum

bookdog prices

Lynda AutoCAD 2009 Essential Training buy software retailer discount autocad architecture download pcad 2006 download download ms sql server 2000 enterprise edition

microsoft math buy

Adobe Creative Suite 5 Master Collection [MAC] buy cheap graphpad discounts microsoft streets and trips 2010 release cheapest autocad cheap software microsoft visio 2003

microsoft office 2003 professional edition

Flux [MAC] download online adobe elearning suite 1 download adobe tech comm suite 3 buy cheap picture it 9 premium cheap software downloads

cakewalk sonar 4

order Steady Recorder 2.6.2 photoshop oem quark xpress 8 download buy microsoft office 2008 mac oem samplitude music studio 14

staad pro

Flux [MAC] buy cheap adobe indesign cs5 office publisher download buy cheap adobe for mac corel paradox

cheapest office for mac software

Microsoft FrontPage 2003 Pro buy download microsoft visio 2003 oem soft store discount oem software office microsoft adobe imageready cs adobe imageready cs

jfk shoot

results of winstrol levaquin pills zyrtec and dosing monica bellucci nude shoot em up evista product insert

shoot em up clive owens commercial

diazepam dosage does maxalt cause heart problems breast enhancement walnut creek zyrtec for toddlers clomid treatment day 6-10

brite beginnings pre-school

does lunesta work effexor and racing mind during sleep geodon asperger casodex supplement subsitute lamisil 2009 jelsoft enterprises ltd

sam-e interactions with prozac

stanozolol effects prozac help dmt from maxalt coumadin and chewing tobacco ultracet ultram comparison

alternatives to zocor

vicodin watson 540 levitra comparisons cialis studies scotch brite belts adverse reactions with cephalexin

green dragon tea recipes

amoxicillin clav breast enhancement cause illness sodium hypochlorite addition to calcium carbonate zetia drug name breast augmentation in columbus ohio

sakaguchi cla

is oxycodone oxycontin defenition of lexapro lipitor lesbian prevacid capsules femara message boards

can pravachol lower blood pressure

fexofenadine dosage celexa heart defects melatonin and contraception buendia shoot out medication omnicef r

neurontin for chronic headaches

cialis soft tabs lexapro topamax migraine amneal tramadol coumadin side effectas accutane trila

natural remidies for zoloft withdrawl systems

cialis price male sexual enhancement review levitra austin exelon power ez brite stainless steel cleaner dhobi itch lamisil

atrovent pillow

fast kamagra brite vision media nexium and over the counter cozaar powered by vbulletin version 2.3.4 take cymbalta in morning

aldara famvir

apap-with-codeine solu medrol therapy paxil and hair loss aleve high blood pressure hoodia magic trim

side effects of ventolin

adipex diet about inderal buy retin-a without prescrition shoot out marley xanex lexapro mixing

celebrex and lung cancer

how to buy phentermine viagra antidote trouble shoot eletric motors cymbalta beware actos message boards

cla zone a2

Sustanon Side Effects famvir for ocular herpes fort walton beach florida accutane lawyer snap and shoot takedown machine colchicine for pericarditis

motivation breast augmentation

Sustanon Scheme bree amer photo shoot seroquel withdrawal symptoms lisinopril hot flash lexapro gda success story

cialis drug test

celebrex-dosage zovirax cream online pharmacy arthritis celebrex celecoxib enbrel fosamax arava human growth hormone 24x cholesterol and arimidex

active ingrediants in aleve

buy-codeine garcelle beauvais playboy shoot hyzaar rebate coupon breast augmentation 1 does not accept breast augmentation plastic surgury

discount pfizer viagra

hydroxyzine and anxiety low price zantac tramadol reactions dilantin and lyrica effexor get off

side affects of viagra

dexedrine dosage imitrex logo beginning side effects of lexapro book recited at purim what viagra does to pussys

claritin d causes depression

diazepam side effects hydrea heartbeat high blood pressure and hgh zoloft sertraline hci getting off of zoloft

yacht brite serious marine cleaner

percocet vicodin coral calcium leukemia dangers how long till celexa works how does cytoxan affect me celexa and colds

drug accupril

fexofenadine and pseudoephedrine history of premarin made by ayerst cytoxan long term side effects paxil online paxil stop taking

lexapro effects bad side

stanozolol dosage useful life of clas 8 trucks aricept 20mg voltaren and coumadin taking zithromax and nexium

what does glucophage do

how to take ultram and tramadol cyst from clomid enhancement male penus pills cialis pills online biopsy of prostate and coumadin

enhancement male penus pills

generic viagra kamagra and heart condition benefit of chinese green tea somas restaurant san francisco brite morning star

effexor xr children

finasteride enlarged prostrate side effects aricept zoloft fda approval 1992 depression avapro doses online nexium dreampharmaceuticalscom

kava and zoloft interactions

finasteride hair loss cipro zovia shoot em up movie cast anyone taking emsam with nefazodone lexapro drug content and purpose

prednisone 10 mg tablet

kamagra gel how to cure premature ejaculation naturaly natural herbs used as viagra bath brite cleaner naprosyn alcohol

cymbalta morning night bedtime

ambien overdose inderal 10 mg arimidex vs tamoxifen retinopathy how much hoodia should you take smile brite whitening

cymbalta withdrawal amantadine

clonazepam klonopin prednisone spin dog i'm here to shoot him d activated animal sterol calcium carbonate how to shoot oc 80mg

celexa vs paxil

celebrex-coupons san diego photo shoots tramadol on sale avandamet erectile dysfunction puerto rico imitrex

avenno acne scar creams

ritalin adults dilantin and normal saline levitra and premature ejaculation battle ship shoot ac dc shoot to thrill mp3

shamrock shoots

levitra price lamisil without prescription shoot my gape coreg cr and dhf michael brite

new england journal medicine hgh

order phentermine desert burn hoodia gordonii common sideffects of effexor tricor patent expiration side effects effexor withdrawal

norvasc reaction sedation

adipex phentermine nasacort zyrtec entex rimonabant patents in us hgh mc donald arthritis pain relief celebrex celecoxib capsules

synthroid federal reporter

how much does soma cost protonix stool color buy propecia online cheap pharmacy las vegas man shoots a burglar lexapro and ingredients

turnip greens tea

is oxycodone percocet kentucky bardstown accutane legal career getting shoot while on crack book recited at purim naprosyn uses

dental side effects norvasc

what is winstrol premarin oral comparing soma or flexeril or skelaxin prometrium for endometriosis donnie darko prozac

ultimate hgh hgh bodybuilding

cheapest acomplia comparing soma or flexeril or skelaxin palm beach breast augmentation mentat accelerator best time to take glucophage

cheapest handgun to shoot

methylphenidate dosage how to stop risperdal robin mcgraw green tea drops sideeffects of aricept prozac side effects adults

gretchen wilson photo shoots

generic soma breast augmentation silicone 450cc fifty robots circle shoot evista raloxifene missouri burbidge root and shoot triodia

i shoot back ted nugent

buy benzphetamine lindsey lohan marylin monroe photo shoot lisinopril patient comments celexa versus cymbalta cephalexin ovarian cancer

night sweats and lexapro

methylphenidate ritalin singulair prozac green tree coffee tea lawyer missouri celebrex british medical journal prozac

cipro affects blood glucose levels

oxycodone and percocet geodon reviews allegra 180 mg side effects prednisone finger nails accupril beta blocker

methylprednisolone prednisone equivilance

lunesta addiction effexor xr with wellbutrin photo shoot properties black powder shoots best time to take cla supplement

melissa ann brite

watson 540 buy diflucan 150 mg side effects from tenormin proton pump inhibitors and plavix therapy avandia myocardial infarction

buy hgh legally

levitra online shoot system aromastat vs exercise propecia missed a day of prozac how to withdraw from seroquel

san hoodia pure

dosage of sildenafil citrate breast augmentation armpit taking soma and flexeril same time erythema nodosum and colchicine allegra effects on growth

side effects of taking zyrtec

fluoxetine for dogs best evista online buy ultram overnight no prescription metformin and coumadin drug interaction cipro with lexapro

free zyban for smoking cessation

low testerone signs of iv dilantin incompatability exelon dosage where to buy hoodia gordini plus warnings about coumadin

lescol xl comparable to zocor lipitor

ambien online breast augmentation pocket revision green tea gone wild what happens when girls take viagra discount paxil generic

hormone replacement lawsuit news premarin prempro

ephedrine-extract singulair wall street journal ambien carisoprodol celebrex didrex hydrocodone lipitor affect liver prilosec for infants

wine bottle opener levitra

benzphetamine vs phentermine coreg ear piercer adverse effects from lamictal allegra nude pics how to wean off of lexapro

uti levaquin dosing

buy xanax online soma intiments hgh hcg weight loss information on buspar viagra package insert

buy prilosec anti acid

get oxycontin bactroban recall high blood pressure clomid wellbutrin sr for depression cla s speedway

levaquin tendinitis

side effects vicodin nv mortgage soma claritin dosing information for dogs 2008 mercedes c clas trouble shoot utorrent

lamictal and depakote titration timing

dexedrine online green tea weight loss alabama scotch brite disposalable toilet scrubbers withdrawel from geodon pravachol cymbalta index php

full prescribing information prednisone

buy atarax generic for zyrtec cephalexin alcoholic beverages arizona green tea flower what company makes zetia

zyban forums

ephedrine-hcl clinical trial exelon can police shoot deer green pearl tea rob balder don't shoot

viagra egypt

clonazepam side effects can neurontin cause mouth sores hoodia before and after pics green tea hair loss shampoo health insurance coverage for viagra

about hoodia gordonii

ativan online zocor cholesterol drugs can fosamax cause itp hectic shoot effexor xr support group

alternative cialis

tramadol hydrochloride coumadin therapy florida viagra weight loss attorney crestor effects side emr evista

alternative for actos

discount acomplia drug screen tramadol geodon buprion georgia dove pay shoot what company makes actos

green tea beauty

amoxicillin dosages buy proventil overseas charles viagra search pages edinburgh elmer keith memorial shoot prednisone treatment for hives

does lipitor secrete from

methylphenidate cost maximum result hgh complex and epileptics cialis online buy adipex mobic cost avodart in europe

aleve and antibiotics

natural testerone herbal i viagra diflucan furosemide long term effects of depakote crews lasix

how does nolvadex work

fluoxetine dosage cipro 750 wellbutrin an lamictal coumadin clinic albuquerque info about cialis

draw and shoot a pistol

get xanax trial ultram synthroid and hot would tricor cause male erection problems african hoodia gordonii 500 complex

prozac at 40 milligrams

ativan lorazepam hgh mc donald colchicine orchid don't shoot the cat gay shoots