require 'eventmachine' require 'sequel' class MarcoPolo attr_reader :locations, :db def initialize @pool_range = 0..99 # I'm not using this (yet?) ... but don't want to forget how I did it # @pool = [].tap do |board| # @pool_range.each do |y| # board << [].tap do |row| # @pool_range.each do |x| # row << "#{y}-#{x}" # end # end # end # end @db = Sequel.connect("postgres://#{ENV['USER']}@localhost/marco_polo", :max_connections => 10) unless @db.table_exists?(:locations) @db.create_table :locations do primary_key :id String :client DateTime :timestamp Integer :x Integer :y constraint(:in_the_pool, 'x > -1 and x < 100 and y > -1 and y < 100') end end @locations = @db[:locations] puts "LET GAME BEGIN NOW" end def polo(client, x, y) @locations.insert(:client => client, :x => x, :y => y, :timestamp => Time.now) nextloc(x, y) end def marco(client = nil) if client @locations.where(:client => client).order_by(:timestamp.desc).first else @locations.order_by(:timestamp.desc).first end end private def nextloc(x, y) # we allow exiting the pool as long as you get back in on the opposite side # a la pac man move_x, move_y = rand(-2..2), rand(-2..2) new_x = x + move_x new_x = 100 + new_x if new_x <= -1 new_y = y + move_y new_y = 100 + new_y if new_y <= -1 [ new_x > 99 ? new_x % 100 : new_x, new_y > 99 ? new_y % 100 : new_y ] end end class MarcoPoloServer < EventMachine::Connection class << self attr_accessor :game end def receive_data(data) parts = data.to_s.split case parts.first when 'polo' client, x, y = parts[1,4] newloc = self.class.game.polo(client, x.to_i, y.to_i) send_data("#{newloc.first} #{newloc.last}\n") when 'marco' if loc = self.class.game.marco(parts[1]) send_data("polo #{loc[:client]} #{loc[:x]} #{loc[:y]}\n") else send_data("polo NULL 0 0\n") end else send_data("#{parts.first}???\n") end rescue => e STDERR.puts("#{e.class.name} #{e.message}: #{e.backtrace.join("\n")}") end end def main MarcoPoloServer.game = MarcoPolo.new EventMachine.run do host, port = '0.0.0.0', 22000 EventMachine.start_server(host, port, MarcoPoloServer) puts "Listening on #{host}:#{port}" end end if $0 == __FILE__ main end