Free tissue packs

This is a common sight at lunchtime in Singapore: tissue packs, often several next to each other, seemingly left behind on the table.

foodcourt

One might, upon first encountering this phenomenon, assume this is the generous act of kind strangers. But it is not. You must not take the tissues. For they have an important message, and that message is this: Go away. Take your food and sit elsewhere, because this seat is taken. I have reserved it with my tissue pack.

It might seem unsporting to use a tissue pack like this. Rude, even. I used to think like that. However, I have come to understand the necessity, and now I too have embraced the tissue-pack culture. If you do not, you will not get a seat. Or you will have a seat, but no food. A regrettable situation.

If you don’t have a tissue pack, don’t worry; there are alternatives. Simply use a similarly unimportant item, such as your work pass, wallet or umbrella. The latter is especially useful for reserving multiple seats or whole tables, depending on the size of the umbrella.

Settling in Singapore

So I’ve been in Singapore just over a week, and so far it’s going pretty great. It’s ridiculously easy to settle in here. Everything is crazily efficient and convenient. I think even if you’d never been here before and wandered around aimlessly for a whole day, you’d still find everything you needed.

I kept my sim card from when I was here on holiday. I switched it over on the plane and it was working before I got off, including data. Brin kept my ez-link (transport) card, so I could start using the trains straight away. You’re never far from somewhere to eat (more on this later), and being a foreigner means my card works in practically any of the ATMs. Not that you need cash most of the time.

I bought a new phone last weekend too (Samsung S4 mini). It wasn’t difficult – every mall has approximately 293 shops selling smartphones. My sim card was too big, so the guy there resized it for me, fit my sd card and applied a screen protector. This is typical service in Singapore. Everything is done for you.

My flat

This is my flat, as seen from the LRT (sort of like a mini train system):

my_flat

And this is the view from my window:

view_from_window

My room’s pretty decent. My housemates are nice, there’s free wifi, and we’ve just had aircon installed. The LRT station is right outside, so it’s very easy to get anywhere from. And it’s only a few blocks away from Brin, which is nice.

Working

I arrived on Thursday and started work on Monday, so I’ve already worked a full week. The office is seriously cool. It’s in a block with a lot of other startups and tech companies, so it’s got a pretty trendy feel to it. The nearest MRT station (one-north) has a Starbucks and a big food court, and a 3-storey gym at the top (although I think membership is about $200 per month, on a 12-month contract).

Our office is small but great. Super modern furniture, Macs everywhere, darts, pool table, tv and console. My colleagues are all around my age and pretty sociable; everyone goes to lunch together and it seems like there’s an event planned every week. Next week we’re going prawning, which is where you ‘fish’ in a pond that’s been conveniently filled with prawns. Then you BBQ and eat them.

The work itself is web development and pretty much what I’m used to, except it’s Ruby on Rails, which is sort of like Perl where someone else has done the work for you.

Eating

Ok, I’ve saved the best until last. The food here is unbelievable. Everywhere you go is packed full with incredible places to eat, every kind of food you can think of, and it’s a fraction of the price you’d pay in the UK. For example, this was my lunch today (Taiwanese hotpot black pepper chicken):

0914_lunch

This cost $5.50, which is about £2.50. I can’t think of anywhere I’d get lunch for less than £3 in Macclesfield, except maybe a cheap sandwich from Tesco. If I’d paid £15 in a British restaurant for my meal today I’d have had no complaints. And $5 isn’t even a cheap meal in Singapore, as Brin keeps telling me. I’ve been doing a lot of eating.

On moving

In a little over 4 weeks I’ll be starting an exciting new chapter in my life. I’ll be moving to Singapore, staying in an area called Sengkang, to be with my girlfriend Brin.

And strangely, I’m not feeling nervous about it. Perhaps I will nearer the time. But I’ve had a lot of time to think about it; pretty much since I met Brin back in January (generally a good idea if you’re getting into a long-distance relationship), so I’m mainly just excited that the day is finally (almost) here!

For the past few weeks I’ve been going through the process of… moving out. Except it’s more than that, because I’m not //just// moving out. I’m leaving my job, saying goodbye to friends and family (don’t worry, I’ll be back) and I don’t have a new home to move into. So I’ve been throwing a lot more stuff out than I normally would moving house, and I’ll be giving a lot away too. I don’t plan to take any more than the essentials to Singapore – clothes, toiletries, phone, iPad, Kindle. Pretty much what I’d normally take on holiday. I’m leaving nearly all my material possessions behind.

I like change. I welcome new challenges and opportunities. But the cost of change, inevitably, is leaving things behind. I imagine that’s fine with most people who move abroad. Maybe they can’t stand the weather here. Maybe they hate their job, or are just fed up, whatever. This doesn’t really apply to me. I think the UK’s pretty amazing, I enjoy my job and have some of the best friends and family around. I have pretty much everything I want here… except Brin. And that is why I’m moving.

But saying that, I don’t feel like I’m ‘leaving everything behind.’ I’m leaving some things behind, sure, like my TV and my CD collection, but not the things that matter. I’ve been 11,000km away from Brin for most of the year and it hardly feels like we’ve been apart. Yes, it’s half way around the world, but there’s Skype (well, Google Hangouts), email, post and phones. And I hope that some of my friends will visit too.

I feel a bit uncomfortable leaving my job. It’s reassuring, knowing you have money coming in each month. When things go wrong, you’ve still got your job, so must be doing //something// right. Similarly, my flat. It’s pretty nice, and coming home to it gives me a sense of having done pretty well so far. I think I’ve been lucky, but at the same time I think I’ve worked hard too. Yet I don’t regret having to give them up, at all.

It’s //exciting//. Liberating and challenging. I absolutely can’t wait to find out what it feels like to be without these things, that I’ve depended on and taken for granted for as long as I can remember. It’ll probably be the most difficult thing I’ve done. But going out of your comfort zone is sometimes the best way to learn; letting go of some things to try new ones. I want to see if I can be make it work in Singapore.

And there’s a lot more I’m looking forward to about moving too. It’s an amazing country. Super-modern and efficient, a stunningly beautiful skyline, ubiquitous (and delicious) food stalls, a near-perfect transport system, a wealth of culture, and even giant alien trees. It’s the best country I’ve been to, and I look forward to getting to know it better.

It’ll be an adventure, that’s for sure. A challenge too, but I’m quietly confident about everything working out. I’ve got accommodation sorted and enough money saved up to stay there a while. I don’t think it’ll be a problem adapting to life there. But more importantly, I won’t be alone. I’ll be with Brin.

Bring on September. 🙂

Writing a poker server in Ruby: part 1

About a month ago I embarked on the project of writing a poker bot. It has all the things I enjoy about programming: it’s open-ended and can always be improved, it can be played against, and AI features heavily. There’s also a wealth of research on the topic: poker-ai.org and The University of Alberta Computer Poker Research Group are the two sites I use the most.

I started by plugging in to Poker Academy, a game featuring strong AI opponents and a decent user interface. It allows you to hook in your own bots using their own Java-based API, called Meerkat. This was and still is a great tool to test with, but it has its drawbacks. You can only run one instance at once, it’s quite slow, and it has no networking capability. I wanted something I could use to demo the bot online.

So, inevitably, I ended up writing a poker server. I’d already written most of the game engine out of necessity for the poker bot; it had to model and understand the game before it could play it. The challenge was to extract this engine out of the code, and build it into a multi-client game server.

For the server to be useful, it had to meet a few basic requirements:

  • It must handle multiple games at once
  • It must support bot and human players
  • It must be accessible via a browser; no downloads
  • It must not be limited to one particular protocol
  • The poker server should not be coupled to a webserver

The key features here are concurrency, scalability and loose coupling. I first needed something to handle the networking, and EventMachine was the obvious choice (I’m using Ruby for this, not Perl.) EventMachine supports many protocols, so I’d support plain TCP for remote bot/telnet clients. But because the main interface will be web-based, I decided to build in WebSocket support right away.

The good news is that EventMachine already has a WebSocket server. Unfortunately, it works a little differently to the TCP server, so I had to create a generic connection handler that could wrap TCP, WebSocket and other connections.

The main EventMachine loop simply starts the various servers. For now I just have TCP, keyboard and WebSocket servers:

    def start
      # Start listening on various protocols: keyboard, telnet and websocket.
      # Players can use any of these.
      EventMachine.run do
        create_games_from_config
        EventMachine.start_server("0.0.0.0", 10000, Merlion::Lobby::TelnetServer, self)
        EM.open_keyboard(Merlion::Lobby::KeyboardHandler, self)
        Merlion::Lobby::WebSocketServer.instance.init(self)
        Merlion::Lobby::WebSocketServer.instance.start_server
      end
    end

Each type of connection needs to implement two basic things:

  • handle: Handling a command from the client
  • write: Sending data to the client

To handle these in a generic way, I’ve written a module called ConnHelper, designed to be mixed into Connection classes. ConnHelper implements handle, and the Connection class should implement write.

When a message comes in, it’s handled by a Connection object. This could be a subclass of EventMachine::Connection or in the case of WebSocket, a separate WebSocketConnection which I’ve implemented. These classes all include the ConnHelper module. The job of the Connection class is to:

  • Process incoming messages and pass them to handle()
  • Implement write so that messages can be sent back to the client.

For TCP clients, this is straightforward:

    class TelnetServer < Merlion::Lobby::TextClient
      include Merlion::Lobby::ConnHelper

      def receive_data(data)
        handle(data)
      end

      def write(msg, channel)
        send_data(msg)
      end
    end

But for WebSocket, it’s a little bit trickier. We need to create a WebSocketConnection when the client connects, and marshal messages to it like so:

def start_server
  EM::WebSocket.start(:host => '0.0.0.0', :port => 11111) do |ws|
    ws.onopen do |handshake|
      @ws_conns[ws.object_id] = Merlion::Lobby::WebSocketConnection.new(ws, self.lobby)
    end
    ws.onmessage do |msg|
      = @ws_conns[ws.object_id]
      obj.handle(msg)
    end
  end
end

Finally, WebSocketConnection implements write, so we can write data to WebSocket clients. Because the WebSocket client is likely to be a JavaScript and not a human, we can take advantage of JSON to provide extra information about the state of the game. So write does not write raw strings; instead, it converts the message to JSON and sends that. In addition, it includes the notion of a ‘channel’ to describe the type of message. This makes it easier to handle on the client side, which I’ll explain in a later post.

class WebSocketConnection < JSONClient
  def initialize(ws, lobby)
    @ws = ws
    @lobby = lobby
  end

  def write(msg, channel)
    payload = {
      merlion: [channel, msg]
    }.to_json
    @ws.send(payload)
  end
end

And that’s my basic framework for message handling in the poker server. It can receive data from any EventMachine servers and handle them in a generic way. When we want to write to the client, we just need to call write on the connection object and it’ll do the right thing. And it’s all asynchronous.

You might have noticed this doesn’t have anything to do with poker. You would be correct; it doesn’t have anything to do with poker. For that, we’d have to implement handle and connect players to the games, calling write at significant points in the game so the client knows what’s going on. But I’ll save that for another blog post 🙂

-Mike