├── .gitignore ├── lib ├── models │ ├── model.coffee │ ├── server │ │ ├── map.coffee │ │ ├── player.coffee │ │ ├── chunkCollection.coffee │ │ ├── chunk.coffee │ │ └── region.coffee │ ├── connector │ │ └── client.coffee │ ├── master │ │ └── world.coffee │ ├── mapCollection.coffee │ ├── gridCollection.coffee │ └── collection.coffee ├── controllers │ ├── server │ │ ├── playerSettings.coffee │ │ ├── motd.coffee │ │ ├── commands.coffee │ │ ├── playerStorage.coffee │ │ ├── animation.coffee │ │ ├── time.coffee │ │ ├── playerList.coffee │ │ ├── keys.coffee │ │ ├── chat.coffee │ │ ├── build.coffee │ │ ├── inventory.coffee │ │ ├── neighbors.coffee │ │ ├── snake.coffee │ │ ├── players.coffee │ │ ├── regions.coffee │ │ ├── playerMovement.coffee │ │ ├── chunks.coffee │ │ └── maps.coffee │ ├── master │ │ ├── chat.coffee │ │ ├── web.coffee │ │ ├── worlds.coffee │ │ ├── players.coffee │ │ ├── db.coffee │ │ └── regions.coffee │ └── connector │ │ ├── handoff.coffee │ │ └── data.coffee ├── generators │ └── superflat.coffee ├── storage │ ├── simple.coffee │ └── s3.coffee ├── server.coffee ├── master.coffee ├── eventstack.coffee ├── connector.coffee ├── component.coffee └── web │ └── index.html ├── package.json ├── config.coffee ├── README.md └── bin └── redstone /.gitignore: -------------------------------------------------------------------------------- 1 | data 2 | node_modules -------------------------------------------------------------------------------- /lib/models/model.coffee: -------------------------------------------------------------------------------- 1 | EventStack = require '../eventstack' 2 | 3 | class Model extends EventStack 4 | 5 | module.exports = Model -------------------------------------------------------------------------------- /lib/controllers/server/playerSettings.coffee: -------------------------------------------------------------------------------- 1 | module.exports = -> 2 | @on 'join:before', (e, player) -> 3 | player.on 0xcc, (e, @settings) -> 4 | @emit 'settings', @settings -------------------------------------------------------------------------------- /lib/controllers/master/chat.coffee: -------------------------------------------------------------------------------- 1 | module.exports = -> 2 | @on 'peer.server', (e, server, connection) => 3 | connection.on 'message', (message) => 4 | for s in @peers.servers.models 5 | s.connection.emit 'message', message if s != server -------------------------------------------------------------------------------- /lib/controllers/server/motd.coffee: -------------------------------------------------------------------------------- 1 | module.exports = (config) -> 2 | motd = config.motd 3 | 4 | if motd? 5 | motd = [motd] if typeof motd == 'string' 6 | 7 | @on 'join:after', (e, player, options) -> 8 | if not options.handoff? 9 | player.on 'ready:after', -> 10 | player.message message for message in motd -------------------------------------------------------------------------------- /lib/controllers/server/commands.coffee: -------------------------------------------------------------------------------- 1 | module.exports = -> 2 | @on 'message', (e, player, message) => 3 | if message.charAt(0) == '/' 4 | command = message.substr 1 5 | player.emit 'command', command 6 | player.emit 'command.'+command 7 | @emit 'command', player, command 8 | @emit 'command.'+command, player 9 | 10 | e.halt() -------------------------------------------------------------------------------- /lib/controllers/server/playerStorage.coffee: -------------------------------------------------------------------------------- 1 | module.exports = (config) -> 2 | cb = (err) => @error err if err 3 | 4 | @on 'join:before', (e, player) => 5 | player.storage = {} if not player.storage? 6 | 7 | player.save = => 8 | @master.request 'db.update', 'players', {username: player.username}, 9 | {$set: {storage: player.storage}}, cb 10 | 11 | # TODO: save on an interval? 12 | 13 | player.on 'quit', player.save -------------------------------------------------------------------------------- /lib/controllers/master/web.coffee: -------------------------------------------------------------------------------- 1 | express = require 'express' 2 | _ = require 'underscore' 3 | 4 | module.exports = (config) -> 5 | app = express() 6 | app.use express.static __dirname+'/../../web' 7 | 8 | app.get '/worlds', (req, res) => 9 | res.json @worlds.models 10 | 11 | app.get '/servers', (req, res) => 12 | res.json _.map @peers.models, (o) -> _.pick o, 'type', 'address', 'id', 'stats' 13 | 14 | app.listen config.webPort or 80 -------------------------------------------------------------------------------- /lib/controllers/connector/handoff.coffee: -------------------------------------------------------------------------------- 1 | module.exports = -> 2 | 3 | @on 'peer.server', (e, server) => 4 | 5 | server.connection.on 'handoff', @getClients (clients, server, player, options) => 6 | client = clients[0] 7 | if client? 8 | @connect server, (newServer) => 9 | oldServer = client.server 10 | @debug "handing off #{client.username}/#{client.id} to server:#{newServer.id}" 11 | client.server = newServer 12 | client.server.connection.emit 'join', player, options -------------------------------------------------------------------------------- /lib/generators/superflat.coffee: -------------------------------------------------------------------------------- 1 | module.exports = (options) -> 2 | blocks = options?.blocks or [ 3 | {type: 7, height: 1} 4 | {type: 3, height: 2} 5 | {type: 2, height: 1} 6 | ] 7 | 8 | (chunk, chunkX, chunkZ) -> 9 | y = 0 10 | for block, i in blocks 11 | for j in [0...block.height] 12 | for x in [0...16] 13 | for z in [0...16] 14 | chunk.setBlock block.type, x, y, z 15 | y++ 16 | 17 | # TODO: do real lighting instead of just lighting everything 18 | chunk.skylight.fill 0xff -------------------------------------------------------------------------------- /lib/storage/simple.coffee: -------------------------------------------------------------------------------- 1 | fs = require 'fs' 2 | Chunk = require '../models/server/chunk' 3 | 4 | module.exports = (options) -> 5 | getFilename = (x, z) -> options.path + "/#{x}.#{z}.chunk" 6 | 7 | get: (x, z, cb) -> 8 | filename = getFilename(x, z) 9 | fs.exists filename, (exists) -> 10 | if exists 11 | fs.readFile filename, (err, data) -> 12 | return cb err if err 13 | cb null, new Chunk data 14 | else cb null 15 | 16 | set: (chunk, x, z, cb) -> 17 | fs.writeFile getFilename(x, z), chunk.buf, cb 18 | 19 | -------------------------------------------------------------------------------- /lib/controllers/master/worlds.coffee: -------------------------------------------------------------------------------- 1 | Collection = require '../../models/collection' 2 | World = require '../../models/master/world' 3 | 4 | module.exports = (config) -> 5 | @worlds = new Collection 6 | 7 | @on 'db.ready:after', (e) => 8 | @db.ensureIndex 'worlds', {id: 1} 9 | 10 | @db.find 'worlds', {}, (err, worlds) => 11 | return @error err if err 12 | @worlds.insert new World world for world in worlds 13 | 14 | if config.worlds? 15 | for world in config.worlds 16 | existing = @worlds.get world.id if world.id? 17 | @worlds.insert new World world if not existing? -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redstone", 3 | "version": "0.1.0", 4 | "description": "A fast, scalable Minecraft server", 5 | "main": "bin/redstone", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": "", 10 | "author": "Matt Bell ", 11 | "license": "BSD", 12 | 13 | "dependencies": { 14 | "minecraft-protocol": "0.11.6", 15 | "coffee-script": "1.4.0", 16 | "winston": "0.6.2", 17 | "commander": "1.1.1", 18 | "underscore": "1.4.3", 19 | "mongodb": "1.2.x", 20 | "async": "0.2.x", 21 | "sock": "0.0.6", 22 | "aws-sdk": "0.9.x", 23 | "express": "3.2.6" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/storage/s3.coffee: -------------------------------------------------------------------------------- 1 | Chunk = require '../models/server/chunk' 2 | aws = require 'aws-sdk' 3 | 4 | getKey = (x, z) -> "#{x}.#{z}.chunk" 5 | 6 | module.exports = (options) -> 7 | aws.config.update options.awsOptions 8 | 9 | s3 = new aws.S3(options.awsOptions).client 10 | s3.createBucket {Bucket: options.bucket} 11 | 12 | get: (x, z, cb) -> 13 | params = 14 | Bucket: options.bucket 15 | Key: getKey x, z 16 | s3.getObject params, (err, data) -> 17 | chunk = new Chunk data.Body if data 18 | cb null, chunk 19 | 20 | set: (chunk, x, z, cb) -> 21 | params = 22 | Bucket: options.bucket 23 | Key: getKey x, z 24 | Body: chunk.buf 25 | s3.putObject params, cb 26 | 27 | -------------------------------------------------------------------------------- /lib/controllers/connector/data.coffee: -------------------------------------------------------------------------------- 1 | protocol = require('minecraft-protocol').protocol 2 | 3 | convertSlot = (slot) -> 4 | slot.nbtData = new Buffer slot.nbtData if slot.nbtData? 5 | 6 | module.exports = -> 7 | 8 | @on 'peer.server', (e, server) => 9 | 10 | server.connection.on 'data', @getClients (clients, id, data) => 11 | packet = protocol.get id, false 12 | 13 | for field in packet 14 | if field.type == 'slot' 15 | convertSlot data[field.name] 16 | else if field.type == 'slotArray' 17 | convertSlot slot for slot in data[field.name] 18 | 19 | for client in clients 20 | if client? 21 | try 22 | client.send id, data 23 | catch err 24 | @error new Error "Error sending data to client: (0x#{id.toString 16}) #{err}" if err? -------------------------------------------------------------------------------- /lib/controllers/server/animation.coffee: -------------------------------------------------------------------------------- 1 | module.exports = -> 2 | 3 | @on 'join:after', (e, player) -> 4 | player.heldSlot = 0 5 | player.on 'ready', -> sendHeldItem player 6 | 7 | options = 8 | radius: 64 9 | exclude: [player] 10 | 11 | sendHeldItem = -> 12 | packet = 13 | entityId: player.entityId 14 | slot: 0 15 | item: player.inventory[player.heldSlot+36] or {id: -1} 16 | player.region.send player.position, options, 0x5, packet 17 | 18 | player.on 0x12, (e, packet) -> 19 | if packet.animation == 1 and packet.entityId == player.entityId 20 | player.region.send player.position, options, 0x12, packet 21 | 22 | player.on 0x10, (e, packet) -> 23 | player.heldSlot = packet.slotId 24 | sendHeldItem player 25 | 26 | # TODO: broadcast held item when other players join -------------------------------------------------------------------------------- /lib/controllers/server/time.coffee: -------------------------------------------------------------------------------- 1 | incrementTime = -> 2 | @time += 20 3 | 4 | startTime = -> 5 | @timeTimer = setInterval @incrementTime, 1000 6 | 7 | sendTime = -> 8 | @send 0x4, {age: [0, @region.ticks], time: [0, @region.time]} 9 | 10 | module.exports = -> 11 | @on 'region:before', (e, region) -> 12 | region.incrementTime = incrementTime.bind region 13 | region.startTime = startTime.bind region 14 | 15 | if region.world.time? 16 | region.time = region.world.time 17 | else 18 | region.time = 0 19 | region.startTime() 20 | 21 | @on 'join:before', (e, player) -> 22 | player.sendTime = sendTime.bind player 23 | player.on 'ready', player.sendTime 24 | player.timeTimer = setInterval player.sendTime, 60 * 1000 25 | 26 | player.on 'leave:before', -> 27 | clearInterval player.timeTimer 28 | delete player.timeTimer -------------------------------------------------------------------------------- /lib/models/server/map.coffee: -------------------------------------------------------------------------------- 1 | Model = require '../model' 2 | 3 | MAP_SIZE = 128 4 | HEADER_LENGTH = 3 5 | COL_LENGTH = MAP_SIZE+HEADER_LENGTH 6 | 7 | class Map extends Model 8 | constructor: (id) -> 9 | @id = id or 0 10 | @cols = [] 11 | @buf = new Buffer COL_LENGTH * MAP_SIZE 12 | @buf.fill 0 13 | 14 | for x in [0...MAP_SIZE] 15 | buf = @buf.slice x * COL_LENGTH, (x+1) * COL_LENGTH 16 | buf[1] = x 17 | @cols[x] = 18 | buf: buf 19 | updated: false 20 | 21 | getPixel: (x, y) -> 22 | @cols[x].buf[y+HEADER_LENGTH] 23 | 24 | setPixel: (value, x, y) -> 25 | @cols[x].buf[y+HEADER_LENGTH] = value 26 | @cols[x].updated = true 27 | 28 | sendTo: (player, all) -> 29 | packet = 30 | type: 358 31 | itemId: @id 32 | 33 | for col in @cols 34 | if col.updated or all 35 | col.updated = false if not all 36 | packet.text = col.buf.toString 'ascii' 37 | player.send 0x83, packet 38 | 39 | 40 | module.exports = Map -------------------------------------------------------------------------------- /lib/models/connector/client.coffee: -------------------------------------------------------------------------------- 1 | Model = require '../model' 2 | _ = require 'underscore' 3 | 4 | ignore = {0xa: 1} 5 | 6 | class Client extends Model 7 | constructor: (options) -> 8 | super() 9 | _.extend @, options 10 | 11 | start: => 12 | @connection.on 'end', => 13 | @sendServer 'quit' 14 | @emit 'quit' 15 | 16 | # when we recieve data from the client, send it to the server 17 | @connection.on 'packet', (packet) => 18 | @sendServer 'data', packet.id, packet if not ignore[packet.id] 19 | 20 | @server.connection.emit 'join', @toJson(), {} 21 | 22 | send: (id, data) => 23 | if id == 0xff then @connection.end data.reason 24 | else @connection.write id, data 25 | 26 | kick: (reason) => 27 | @connection.end reason 28 | 29 | sendServer: => 30 | args = Array::slice.call arguments, 0 31 | args.splice 1, 0, @id 32 | @server.connection.emit.apply @server.connection, args 33 | 34 | toJson: => 35 | _.omit @, 'server', 'connection', 'stacks', _.functions(@) 36 | 37 | module.exports = Client -------------------------------------------------------------------------------- /lib/models/server/player.coffee: -------------------------------------------------------------------------------- 1 | Model = require '../model' 2 | _ = require 'underscore' 3 | 4 | class Player extends Model 5 | constructor: (options) -> 6 | super() 7 | options = options or {} 8 | @[k] = v for k,v of options 9 | 10 | @userId = @username.toLowerCase() 11 | 12 | _send: (event) => 13 | args = [event, @id] 14 | args = args.concat Array::slice.call(arguments, 1) 15 | @connector.connection.emit.apply @connector.connection, args 16 | 17 | send: (id, data) => 18 | @_send 'data', id, data 19 | 20 | kick: (reason) => 21 | @kicked = true 22 | @send 0xff, reason: reason 23 | 24 | ping: (cb) -> 25 | id = Math.floor Math.random() * 0xffffffff / 2 26 | start = Date.now() 27 | onPong = (e, packet) -> 28 | if packet.keepAliveId == id 29 | @off 0x0, onPong 30 | cb Date.now() - start 31 | @on 0x0, onPong 32 | @send 0x0, keepAliveId: id 33 | 34 | toJson: -> 35 | json = _.omit @, 'connector', 'stacks', _.functions(@) 36 | @emit 'toJson', json 37 | json 38 | 39 | module.exports = Player -------------------------------------------------------------------------------- /lib/controllers/server/playerList.coffee: -------------------------------------------------------------------------------- 1 | updatePing = -> 2 | @ping (latency) => 3 | @latency = latency 4 | 5 | packet = 6 | online: true 7 | ping: latency 8 | 9 | packet.playerName = @username 10 | @region.send 0xc9, packet 11 | 12 | module.exports = -> 13 | @on 'join:after', (e, player) => 14 | player.updatePing = updatePing.bind player 15 | pingTimer = null 16 | 17 | player.on 'ready:after', (e) => 18 | player.updatePing() 19 | pingTimer = setInterval player.updatePing, 30 * 1000 20 | 21 | packet = online: true 22 | 23 | for p in player.region.players.models 24 | packet.playerName = p.username 25 | packet.ping = p.latency or 0 26 | player.send 0xc9, packet 27 | 28 | player.on 'leave:after', (e) => 29 | packet = 30 | playerName: player.username 31 | online: false 32 | ping: 0 33 | 34 | player.region.send 0xc9, packet 35 | 36 | for p in player.region.players.models 37 | player.send 0xc9, 38 | online: false 39 | playerName: p.username 40 | ping: 0 -------------------------------------------------------------------------------- /config.coffee: -------------------------------------------------------------------------------- 1 | packageJson = JSON.parse require('fs').readFileSync('./package.json', 'utf8') 2 | nodeVersion = process.versions.node 3 | redstoneVersion = packageJson.version 4 | 5 | module.exports = 6 | motd: [ 7 | '§cWelcome to the Redstone test server!' 8 | "Running Node.js §a#{nodeVersion}§r, Redstone §a#{redstoneVersion}" 9 | 'This server is experimental, so expect bugs' 10 | ] 11 | 12 | worlds: [ 13 | id: 'main' 14 | persistent: true 15 | ] 16 | 17 | saveInterval: 5 * 60 * 1000 # how often to save chunks inside the region 18 | chunkReloadInterval: 60 * 1000 # how often we should reload neighboring chunks 19 | chunkUnloadDelay: 2 * 60 * 1000 # how long a chunk should be inactive before unloading 20 | chunkInterval: 10 # how long to wait in between sending chunks (to prevent locking up) 21 | 22 | remapInterval: 10 * 60 * 1000 23 | remapDelay: 20 * 1000 24 | 25 | spawnDelay: 250 26 | readyDelay: 0 27 | 28 | connector: 29 | 'online-mode': false 30 | encryption: false 31 | motd: 'Redstone test server' 32 | 'max-players': '0' 33 | 34 | database: 'mongodb://localhost/redstone' -------------------------------------------------------------------------------- /lib/controllers/server/keys.coffee: -------------------------------------------------------------------------------- 1 | MARGIN = 35 2 | 3 | onMove = (e, d) -> 4 | player = e.origin 5 | 6 | facing = player.position.yaw % 360 7 | facing += 360 if facing < 0 8 | 9 | moving = Math.atan2 d.z, d.x 10 | moving *= 180 / Math.PI 11 | moving -= 90 12 | moving += 360 if moving < 0 13 | 14 | diff = facing - moving 15 | diff += 360 if diff < 0 16 | 17 | pressed = 18 | w: diff > 270 + MARGIN or diff < 90 - MARGIN 19 | s: 90 + MARGIN < diff < 270 - MARGIN 20 | a: MARGIN < diff < 180 - MARGIN 21 | d: 180 + MARGIN < diff < 360 - MARGIN 22 | 23 | for key, v of pressed 24 | if v 25 | player.emit 'key.'+key if not player.wasPressed[key] 26 | player.wasPressed[key] = true 27 | else player.wasPressed[key] = false 28 | 29 | enableKeys = -> 30 | @keysEnabled = true 31 | @wasPressed = {} 32 | @on 'move:after', onMove 33 | 34 | disableKeys = -> 35 | delete @keysEnabled 36 | delete @wasPressed 37 | @off 'move:after', onMove 38 | 39 | module.exports = -> 40 | @on 'join:after', (e, player) -> 41 | player.enableKeys = enableKeys.bind player 42 | player.disableKeys = disableKeys.bind player -------------------------------------------------------------------------------- /lib/server.coffee: -------------------------------------------------------------------------------- 1 | Component = require './component' 2 | 3 | class Server extends Component 4 | constructor: (config, control, master) -> 5 | @type = 'server' 6 | super config, control, master 7 | 8 | start: -> 9 | # load core modules 10 | @use require '../lib/controllers/server/players' 11 | @use require '../lib/controllers/server/playerStorage' 12 | @use require '../lib/controllers/server/playerMovement' 13 | @use require '../lib/controllers/server/regions' 14 | @use require '../lib/controllers/server/chat' 15 | @use require '../lib/controllers/server/commands' 16 | @use require '../lib/controllers/server/inventory' 17 | @use require '../lib/controllers/server/animation' 18 | @use require '../lib/controllers/server/chunks' 19 | @use require '../lib/controllers/server/build' 20 | @use require '../lib/controllers/server/time' 21 | @use require '../lib/controllers/server/maps' 22 | @use require '../lib/controllers/server/keys' 23 | @use require '../lib/controllers/server/snake' 24 | @use require '../lib/controllers/server/playerList' 25 | @use require '../lib/controllers/server/motd' 26 | @use require '../lib/controllers/server/playerSettings' 27 | @use require '../lib/controllers/server/neighbors' 28 | 29 | super() 30 | 31 | module.exports = Server -------------------------------------------------------------------------------- /lib/master.coffee: -------------------------------------------------------------------------------- 1 | Component = require './component' 2 | _ = require 'underscore' 3 | 4 | class Master extends Component 5 | constructor: (config, iface) -> 6 | @type = 'master' 7 | super config, iface 8 | 9 | start: -> 10 | # load core modules 11 | @use require '../lib/controllers/master/db' 12 | @use require '../lib/controllers/master/worlds' 13 | @use require '../lib/controllers/master/regions' 14 | @use require '../lib/controllers/master/players' 15 | @use require '../lib/controllers/master/chat' 16 | @use require '../lib/controllers/master/web' 17 | 18 | @players = 0 19 | @on 'peer', (e, peer, connection) => 20 | peer.stats = {} 21 | 22 | connection.on 'update', (data) => 23 | peer.stats = _.extend peer.stats, data 24 | @debug "got update from #{peer.type}:#{peer.id}" 25 | @emit "peer.update", peer, peer.stats 26 | @emit "peer.#{peer.type}.update", peer, peer.stats 27 | 28 | @connectorUpdateTimer = setInterval @updateConnectors, 10 * 1000 29 | 30 | updateConnectors: => 31 | @players = 0 32 | @players += server.stats.players for server in @peers.servers.models 33 | 34 | data = 35 | players: @players 36 | 37 | connector.connection.emit 'update', data for connector in @peers.connectors.models 38 | 39 | module.exports = Master -------------------------------------------------------------------------------- /lib/controllers/master/players.coffee: -------------------------------------------------------------------------------- 1 | _ = require 'underscore' 2 | 3 | module.exports = -> 4 | @on 'db.ready:after', => 5 | @db.ensureIndex 'players', {username: 1} 6 | 7 | @on 'join', (e, player, res) => 8 | @db.findOne 'players', _.pick(player, 'username'), (err, doc) => 9 | return @error err if err 10 | 11 | storage = doc?.storage 12 | player.storage = storage or {} 13 | 14 | # TODO: get default world from somewhere 15 | player.storage.world = 'main' if not player.storage.world? 16 | world = @worlds.get player.storage.world 17 | 18 | if not player.storage.position? 19 | # TODO: allow spawning in a random spot in an area 20 | # TODO: distribute spawns across a list of points/areas 21 | player.storage.position = 22 | if world.spawn? then _.clone world.spawn 23 | else 24 | x: 0 25 | y: 128 26 | z: 0 27 | yaw: 0 28 | pitch: 0 29 | 30 | chunkX = Math.floor player.storage.position.x / 16 31 | chunkZ = Math.floor player.storage.position.z / 16 32 | # TODO: figure out what to do if the chunk is unmapped 33 | regionId = world.map[chunkX]?[chunkZ]?.region or Math.floor Math.random() * @peers.servers.length 34 | server = world.servers[regionId] 35 | 36 | res server, player 37 | 38 | if not storage 39 | player.created = Date.now() 40 | @db.insert 'players', player, (err) => @error err if err 41 | 42 | @on 'peer.connector', (e, connector, connection) => 43 | connection.respond 'join', (res, player) => 44 | @emit 'join', player, res -------------------------------------------------------------------------------- /lib/models/server/chunkCollection.coffee: -------------------------------------------------------------------------------- 1 | Model = require '../model' 2 | GridCollection = require '../gridCollection' 3 | Chunk = require './chunk' 4 | 5 | class ChunkCollection extends Model 6 | constructor: (options) -> 7 | @storage = options?.storage 8 | @generator = options?.generator 9 | 10 | @chunks = new GridCollection 11 | 12 | getChunk: (x, z, cb) -> 13 | cb = cb or -> 14 | chunk = @chunks.get x, z 15 | 16 | if not chunk 17 | chunk = new Chunk 18 | @chunks.set chunk, x, z 19 | 20 | generate = => @generateChunk x, z, cb 21 | 22 | if @storage? then @loadChunk x, z, (err, chunk) -> 23 | if err? or chunk? then cb err, chunk 24 | else generate() 25 | else generate() 26 | else 27 | cb null, chunk 28 | 29 | setChunk: (chunk, x, z) -> 30 | @chunks.set chunk, x, z 31 | 32 | generateChunk: (x, z, cb) -> 33 | cb = cb or -> 34 | chunk = new Chunk 35 | if typeof @generator == 'function' then @generator chunk, x, z 36 | else if @generator instanceof Array 37 | generator chunk, x, z for generator in @generator 38 | chunk.lastUpdate = Date.now() 39 | @setChunk chunk, x, z 40 | cb null, chunk 41 | 42 | loadChunk: (x, z, cb) -> 43 | cb = cb or -> 44 | @storage.get x, z, (err, chunk) => 45 | return cb err if err? 46 | if chunk? 47 | chunk.lastUpdate = Date.now() 48 | @setChunk chunk, x, z 49 | cb null, chunk 50 | 51 | storeChunk: (x, z, cb) -> 52 | cb = cb or -> 53 | @getChunk x, z, (err, chunk) => 54 | return cb err if err? 55 | chunk.lastSave = Date.now() 56 | @storage.set chunk, x, z, cb 57 | 58 | unloadChunk: (x, z) -> 59 | @chunks.remove x, z 60 | 61 | module.exports = ChunkCollection -------------------------------------------------------------------------------- /lib/controllers/server/chat.coffee: -------------------------------------------------------------------------------- 1 | text = 2 | black: '§0', 3 | darkBlue: '§1', 4 | darkGreen: '§2', 5 | darkAqua: '§3', 6 | darkRed: '§4', 7 | purple: '§5', 8 | gold: '§6', 9 | grey: '§7', 10 | darkGrey: '§8', 11 | indigo: '§9', 12 | green: '§a', 13 | aqua: '§b', 14 | red: '§c', 15 | pink: '§d', 16 | yellow: '§e', 17 | white: '§f', 18 | random: '§k', 19 | bold: '§l', 20 | strike: '§m', 21 | underline: '§n', 22 | italic: '§o', 23 | reset: '§r' 24 | 25 | jsonify = (message) -> JSON.stringify({text: message}) 26 | 27 | module.exports = -> 28 | @prefixes = 29 | chat: '' 30 | system: text.yellow 31 | 32 | @broadcast = (message) => 33 | @master.emit 'message', message 34 | 35 | @on 'region:before', (e, region) => 36 | region.broadcast = (message) => 37 | region.send 0x3, {message: jsonify message } 38 | 39 | @master.on 'message', (message) -> 40 | region.broadcast message 41 | 42 | @on 'join:before', (e, player) -> 43 | player.message = (message) => player.send 0x3, message: jsonify message 44 | 45 | @on 'join:after', (e, player, options) => 46 | if not options.handoff? 47 | player.region.broadcast @prefixes.system + "#{player.username} joined the game" 48 | 49 | player.on 0x3, (e, data) => 50 | player.emit 'message', data.message 51 | @emit 'message', player, data.message 52 | 53 | @on 'quit:after', (e, player) => 54 | player.region.broadcast @prefixes.system + "#{player.username} left the game" 55 | 56 | @on 'message', (e, player, message) => 57 | formatted = "<#{player.username}> #{message}" 58 | player.region.send 0x3, {message: jsonify formatted} 59 | @broadcast formatted 60 | @log 'chat', "[#{player.region.id}] #{formatted}" -------------------------------------------------------------------------------- /lib/models/master/world.coffee: -------------------------------------------------------------------------------- 1 | Model = require '../model' 2 | Collection = require '../collection' 3 | GridCollection = require '../gridCollection' 4 | _ = require 'underscore' 5 | 6 | class World extends Model 7 | constructor: (options) -> 8 | _.extend @, options 9 | 10 | @map = new GridCollection 11 | @chunks = [] 12 | 13 | # TODO: figure out which chunks to map initially 14 | for x in [-4..5] 15 | for z in [-4..5] 16 | @getChunk x, z 17 | 18 | @remap() 19 | 20 | # maps chunks into regions based on population 21 | remap: (regions, options) -> 22 | # TODO: refactor to minimize moving regions to new servers 23 | # TODO: use historical population statistics to guess best mapping 24 | # TODO: make less shitty after seeing player behavior (hire someone who is pro?) 25 | regions = regions or 1 26 | @regions = [] 27 | 28 | @chunks.sort (a, b) -> 29 | Math.floor(Math.random() * 3) - 1 30 | 31 | @chunks.sort (a, b) -> 32 | diff = a.players - b.players 33 | if diff > 0 then return -1 34 | else if diff < 0 then return 1 35 | else return 0 36 | 37 | centers = @chunks.slice 0, regions 38 | chunk.region = region for chunk, region in centers 39 | 40 | for chunk in @chunks 41 | closestD = null 42 | for center in centers 43 | d = Math.sqrt Math.pow(chunk.x - center.x, 2) + Math.pow(chunk.z - center.z, 2) 44 | if not closestD? or d < closestD 45 | closestD = d 46 | closestCenter = center 47 | 48 | region = closestCenter.region 49 | chunk.region = region 50 | @regions[region] = @regions[region] or [] 51 | @regions[region].push chunk 52 | 53 | # TODO: balance regions 54 | 55 | getChunk: (x, z) -> 56 | chunk = @map.get x, z 57 | if not chunk? 58 | chunk = {x: x, z: z, players: 0} 59 | @map.set chunk, x, z 60 | @chunks.push chunk 61 | chunk 62 | 63 | module.exports = World -------------------------------------------------------------------------------- /lib/models/mapCollection.coffee: -------------------------------------------------------------------------------- 1 | Collection = require './collection' 2 | GridCollection = require './gridCollection' 3 | 4 | class MapCollection extends Collection 5 | constructor: (models, options) -> 6 | if not options? and not (models instanceof Array) 7 | options = models 8 | models = null 9 | 10 | super models, options 11 | 12 | @options = options or {} 13 | @cellSize = @options.cellSize or 32 14 | @positionKey = @options.positionKey or 'position' 15 | @grid = new GridCollection 16 | @cellMap = {} 17 | 18 | @onMove = @onMove.bind @ 19 | 20 | getCell: (model) -> 21 | position = model[@positionKey] 22 | x = Math.floor position.x / @cellSize 23 | z = Math.floor position.z / @cellSize 24 | cell = @grid.get x, z 25 | if not cell 26 | cell = new Collection @options 27 | @grid.set cell, x, z 28 | cell.x = x 29 | cell.z = z 30 | return cell 31 | 32 | onMove: (e) => 33 | model = e.origin 34 | position = model[@positionKey] 35 | cell = @cellMap[model.id] 36 | x = Math.floor position.x / @cellSize 37 | z = Math.floor position.z / @cellSize 38 | if x != cell.x or z != cell.z 39 | cell.remove model 40 | cell = @getCell model 41 | cell.insert model 42 | @cellMap[model.id] = cell 43 | 44 | insert: (model) -> 45 | super model # hehehe 46 | cell = @getCell model 47 | cell.insert model 48 | @cellMap[model.id] = cell 49 | model.on 'move:after', @onMove 50 | 51 | remove: (model) -> 52 | model = super model 53 | @cellMap[model.id].remove model 54 | delete @cellMap[model.id] 55 | model.off 'move:after', @onMove 56 | 57 | getRadius: (model, radius) -> 58 | position = if model[@positionKey]? then model[@positionKey] else model 59 | x = Math.floor position.x / @cellSize 60 | z = Math.floor position.z / @cellSize 61 | range = Math.ceil radius / @cellSize 62 | cells = [] 63 | for i in [x-range..x+range] 64 | for j in [z-range..z+range] 65 | # TODO: check if models are in radius? 66 | cell = @grid.get i, j 67 | cells.push cell.models if cell? 68 | return Array::concat.apply [], cells 69 | 70 | module.exports = MapCollection -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | redstone 2 | ======== 3 | 4 | A distributed, infinite-player Minecraft server that runs on Node.js. 5 | 6 | Redstone can support theoretically infinite players in one game world by transparently breaking up the work to multiple servers. Being based on Node.js, it has blazing fast IO performance, which means lower resource consumption and lower latency than standard Java servers. 7 | 8 | ## Status 9 | **WARNING:** This project is currently considered unstable and experimental, it is not ready for production yet. 10 | 11 | Redstone currently only supports creative mode, and is missing much of the game logic. The framework for the clustering of servers is present and functional, but could use some reorganization. 12 | This was originally a private project. Since I don't have enough time to spend on it anymore, I am open-sourcing it to allow the community to contribute and progress the code. 13 | When I have time, I will document the current architecture to make it easier to figure out what's going on. 14 | 15 | ## Usage 16 | 17 | First, make sure you have a MongoDB instance running. By default, Redstone connects to a MongoDB server on `localhost`, but if neccessary, you can configure the Mongo URI via the `database` parameter in `config.coffee`. 18 | 19 | Install the dependencies: 20 | ``` 21 | npm install 22 | ``` 23 | 24 | ### Simple mode (all components in one process) 25 | ``` 26 | node bin/redstone.js 27 | ``` 28 | 29 | ### Distributed (components running on separate processes or servers) 30 | First, you must run one master component: 31 | ``` 32 | node bin/redstone.js -m 33 | ``` 34 | 35 | Next, you will need to start the other components (servers and connectors). When starting them, you will need to specify the hostname of the master. You must start at least one server and at least one connector, but you may start as many as you like. 36 | ``` 37 | node bin/redstone.js -s --master= 38 | node bin/redstone.js -c --master= 39 | ``` 40 | 41 | **NOTE:** If multiple components are running on the same machine, you must set the control port to a unique port, e.g.: 42 | ``` 43 | node bin/redstone.js -s --master=localhost --control=8001 44 | node bin/redstone.js -c --master=localhost --control=8002 45 | ``` 46 | 47 | Once your components spin up, you should be able to connect to the connector(s) via your Minecraft client. 48 | -------------------------------------------------------------------------------- /lib/eventstack.coffee: -------------------------------------------------------------------------------- 1 | EVENT_SEPARATOR = ':' 2 | 3 | class EventStack 4 | constructor: -> 5 | @stacks = {} 6 | 7 | on: (event, handler, priority) => 8 | if typeof handler != 'function' 9 | throw new Error 'Event handler must be a function.' 10 | 11 | event = String(event).trim().toLowerCase() 12 | priority = 1 if not priority? 13 | 14 | @stacks[event] = [] if not @stacks[event]? 15 | stacks = @stacks[event] 16 | stacks[priority] = [] if not stacks[priority]? 17 | 18 | if event.indexOf(EVENT_SEPARATOR) != -1 then stacks[priority].push handler 19 | else stacks[priority].splice 0, 0, handler 20 | 21 | once: (event, handler, priority) => 22 | _off = @off 23 | f = -> 24 | args = Array::slice.call arguments, 0 25 | handler.apply @, args 26 | _off event, f 27 | @on event, f, priority 28 | 29 | off: (event, handler) => 30 | event = String(event).trim().toLowerCase() 31 | 32 | stacks = @stacks[event] 33 | for priority in stacks 34 | if priority? 35 | i = priority.indexOf(handler) 36 | return priority.splice i, 1 if i != -1 37 | 38 | emit: (event) => 39 | event = String(event) 40 | 41 | if event.indexOf(EVENT_SEPARATOR) != -1 42 | throw new Error "Tried to emit an event that contained a modifier (#{event})" 43 | 44 | event = event.trim().toLowerCase() 45 | 46 | # create array to be emitted as handler arguments 47 | e = origin: @ 48 | args = Array::slice.call arguments, 1 49 | args.splice 0, 0, e 50 | 51 | # emit event with "before" modifier, then emit on parent 52 | eventSelector = "#{event}#{EVENT_SEPARATOR}before" 53 | @_emit eventSelector, args 54 | @parent._emit eventSelector, args if @parent? 55 | 56 | # emit event, then emit on parent 57 | signal = value: false 58 | e.halt = -> signal.value = true 59 | @_emit event, args, signal 60 | @parent._emit event, args if @parent? 61 | e.halt = undefined 62 | 63 | # emit event with "after" modifier, then emit on parent 64 | eventSelector = "#{event}#{EVENT_SEPARATOR}after" 65 | @_emit eventSelector, args 66 | @parent._emit eventSelector, args if @parent? 67 | 68 | _emit: (event, args, signal) => 69 | if @stacks[event]? and Array.isArray(@stacks[event]) 70 | for stacks in @stacks[event] 71 | if stacks? 72 | for handler in stacks 73 | if signal? and signal.value then return 74 | handler.apply @, args if handler? 75 | 76 | module.exports = EventStack -------------------------------------------------------------------------------- /lib/models/server/chunk.coffee: -------------------------------------------------------------------------------- 1 | Model = require '../model' 2 | zlib = require 'zlib' 3 | 4 | getNibble = (buf, offset) -> 5 | offset /= 2 6 | word = buf[Math.floor offset] 7 | return if offset % 0 == 0 then word & 0xf else (word & 0xf0) >> 4 8 | 9 | setNibble = (buf, value, offset) -> 10 | value &= 0xf 11 | i = Math.floor offset / 2 12 | word = buf[i] 13 | if offset % 2 == 0 14 | word = (word | 0xf) ^ 0xf 15 | word |= value 16 | else 17 | word = (word | 0xf0) ^ 0xf0 18 | word |= value << 4 19 | buf[i] = word 20 | 21 | sizes = 22 | types: 16 * 256 * 16 23 | meta: 16 * 256 * 16 / 2 24 | light: 16 * 256 * 16 / 2 25 | skylight: 16 * 256 * 16 / 2 26 | add: 16 * 256 * 16 / 2 27 | biomes: 16 * 16 28 | 29 | size = 0 30 | size += v for k, v of sizes 31 | 32 | class Chunk extends Model 33 | constructor: (@buf) -> 34 | if not @buf? 35 | @buf = new Buffer size 36 | @buf.fill 0 37 | offset = 0 38 | @[k] = @buf.slice offset, offset += v for k, v of sizes 39 | @lastUpdate = null 40 | 41 | getBlock: (x, y, z) -> 42 | # TODO: set add values 43 | @types[@getOffset x, y, z] 44 | 45 | setBlock: (value, x, y, z) -> 46 | # TODO: get add values 47 | @types[@getOffset x, y, z] = value 48 | @lastUpdate = Date.now() 49 | 50 | getField: (field, x, y, z) -> 51 | getNibble @[field], @getOffset(x, y, z) 52 | 53 | setField: (field, value, x, y, z) -> 54 | setNibble @[field], value, @getOffset(x, y, z) 55 | @lastUpdate = Date.now() 56 | 57 | getOffset: (x, y, z) -> y * 16 * 16 + z * 16 + x % 16 58 | 59 | toPacket: (options, cb) -> 60 | if typeof options == 'function' 61 | cb = options 62 | options = null 63 | 64 | options = options or {} 65 | x = options.x or 0 66 | z = options.z or 0 67 | compress = if options.compress? then options.compress else true 68 | 69 | # TODO: don't always send the whole thing 70 | output = 71 | x: x 72 | z: z 73 | groundUp: true 74 | bitMap: 0xffff 75 | addBitMap: 0 76 | 77 | if compress 78 | if @cachedPacket? and @cachedTime >= @lastUpdate 79 | output.compressedChunkData = @cachedPacket 80 | cb null, output 81 | else 82 | zlib.deflate @buf, (err, data) => 83 | return cb err if err 84 | output.compressedChunkData = data 85 | @cachedTime = Date.now() 86 | @cachedPacket = data 87 | cb null, output 88 | else 89 | output.data = @buf 90 | cb null, output 91 | 92 | module.exports = Chunk -------------------------------------------------------------------------------- /lib/connector.coffee: -------------------------------------------------------------------------------- 1 | Component = require './component' 2 | Collection = require './models/collection' 3 | Client = require './models/connector/client' 4 | mcnet = require 'minecraft-protocol' 5 | _ = require 'underscore' 6 | 7 | class Connector extends Component 8 | constructor: (config, port, master) -> 9 | @type = 'connector' 10 | super config, port, master 11 | 12 | @clients = new Collection [], indexes: ['username'] 13 | 14 | @stats = {} 15 | 16 | start: -> 17 | # load core modules 18 | @use require '../lib/controllers/connector/data' 19 | @use require '../lib/controllers/connector/handoff' 20 | 21 | # listen for client connections 22 | @mcserver = mcnet.createServer @config.connector 23 | @mcserver.on 'error', @error 24 | @mcserver.on 'login', @onPlayerConnect 25 | @mcserver.on 'listening', => 26 | @info "listening for Minecraft connections on port #{@config.connector.port or 25565}" 27 | @emit 'listening' 28 | 29 | # listen for master updates 30 | @master.on 'update', (data) => 31 | @stats = _.extend @stats, data 32 | @mcserver.playerCount = @stats.players 33 | 34 | super() 35 | 36 | onPlayerConnect: (connection) => 37 | connectionJson = 38 | username: connection.username 39 | 40 | # request server to forward player connection to 41 | @master.request 'join', connectionJson, (server, player) => 42 | @connect server, (server) => 43 | player.server = server 44 | player.connection = connection 45 | client = new Client player 46 | 47 | if @clients.get 'username', client.username 48 | return client.kick("Someone named '#{client.username}' is already connected.") 49 | @clients.insert client 50 | 51 | address = "#{client.connection.socket.remoteAddress}:#{client.connection.socket.remotePort}" 52 | @info "#{client.username}/#{client.id} [#{address}] connected" 53 | 54 | client.on 'quit', => 55 | @info "#{connection.username} [#{address}] disconnected" 56 | @clients.remove client 57 | @master.emit 'quit', client.id 58 | 59 | @emit 'join', client 60 | client.start() 61 | 62 | getClient: (id) -> @clients.get id 63 | 64 | getClients: (cb) => (ids) => 65 | if ids instanceof Array 66 | clients = [] 67 | clients.push @getClient id for id in ids 68 | else 69 | clients = [@getClient ids] 70 | 71 | args = [clients] 72 | cb.apply @, args.concat Array::slice.call(arguments, 1) 73 | 74 | module.exports = Connector -------------------------------------------------------------------------------- /lib/controllers/server/build.coffee: -------------------------------------------------------------------------------- 1 | module.exports = -> 2 | @on 'join:after', (e, player) => 3 | 4 | getCoordinates = (x, y, z, face) -> 5 | if face == 0 then y-- 6 | else if face == 1 then y++ 7 | else if face == 2 then z-- 8 | else if face == 3 then z++ 9 | else if face == 4 then x-- 10 | else if face == 5 then x++ 11 | return {x: x, y: y, z: z} 12 | 13 | player.on 0xe, (e, packet) => 14 | # TODO: make sure player isn't cheating 15 | # TODO: support non-creative digging 16 | 17 | if packet.status == 0 18 | chunkX = Math.floor packet.x / 16 19 | chunkZ = Math.floor packet.z / 16 20 | 21 | player.region.chunks.getChunk chunkX, chunkZ, (err, chunk) => 22 | return @error err if err 23 | chunk.setBlock 0, 24 | (packet.x + if packet.x < 0 then 1 else 0) % 16 + if packet.x < 0 then 15 else 0, 25 | packet.y, 26 | (packet.z + if packet.z < 0 then 1 else 0) % 16 + if packet.z < 0 then 15 else 0 27 | 28 | # TODO: set players' chunk load time to chunk.lastUpdate 29 | player.region.send player.position, 0x35, 30 | x: packet.x 31 | y: packet.y 32 | z: packet.z 33 | type: 0 34 | metadata: 0 35 | 36 | player.on 0xf, (e, packet) => 37 | # TODO: make sure player isn't cheating 38 | coords = getCoordinates packet.x, packet.y, packet.z, packet.direction 39 | return if packet.heldItem.id < 0 or packet.heldItem.id > 255 or packet.direction < 0 or 40 | coords.y < 0 or coords.y > 255 41 | 42 | chunkX = Math.floor coords.x / 16 43 | chunkZ = Math.floor coords.z / 16 44 | 45 | player.region.chunks.getChunk chunkX, chunkZ, (err, chunk) => 46 | return @error err if err 47 | 48 | chunkCoords = 49 | x: (coords.x + if coords.x < 0 then 1 else 0) % 16 + if coords.x < 0 then 15 else 0 50 | y: coords.y 51 | z: (coords.z + if coords.z < 0 then 1 else 0) % 16 + if coords.z < 0 then 15 else 0 52 | 53 | chunk.setBlock packet.heldItem.id, chunkCoords.x, chunkCoords.y, chunkCoords.z 54 | chunk.setField 'meta', packet.heldItem.itemDamage, chunkCoords.x, chunkCoords.y, chunkCoords.z 55 | 56 | # TODO: set players' chunk load time to chunk.lastUpdate 57 | player.region.send player.position, 0x35, 58 | x: coords.x 59 | y: coords.y 60 | z: coords.z 61 | type: packet.heldItem.id 62 | metadata: packet.heldItem.itemDamage or 0 -------------------------------------------------------------------------------- /lib/models/server/region.coffee: -------------------------------------------------------------------------------- 1 | Model = require '../model' 2 | MapCollection = require '../mapCollection' 3 | Player = require './player' 4 | _ = require 'underscore' 5 | 6 | class Region extends Model 7 | constructor: (options) -> 8 | super() 9 | options = options or {} 10 | @[k] = v for k,v of options 11 | 12 | if not @tickInterval? then @tickInterval = 1000 / 20 13 | 14 | @ticks = 0 15 | @players = new MapCollection {indexes: ['username'], cellSize: 16} 16 | 17 | @update() 18 | 19 | start: -> 20 | if not @tickTimer 21 | @tickTimer = setInterval @tick.bind(@), @tickInterval 22 | 23 | stop: -> 24 | clearInterval @tickTimer 25 | @tickTimer = null 26 | 27 | tick: -> 28 | @emit 'tick' 29 | @ticks++ 30 | 31 | send: (position, options, id, data) -> 32 | idIndex = 2 33 | if typeof position == 'number' 34 | id = position 35 | data = options 36 | position = null 37 | options = null 38 | idIndex = 0 39 | else if typeof options == 'number' 40 | data = id 41 | id = options 42 | options = null 43 | idIndex = 1 44 | 45 | options = options or 46 | radius: 32 47 | exclude: null 48 | 49 | players = if not position then @players.models else @players.getRadius position, options.radius 50 | players = _.difference players, options.exclude if options.exclude 51 | 52 | connectors = {} 53 | for player in players 54 | connector = connectors[player.connector.id] 55 | if not connector? 56 | connector = connectors[player.connector.id] = 57 | players: [player.id] 58 | connector: player.connector 59 | else connector.players.push player.id 60 | 61 | c.connector.connection.emit 'data', c.players, id, data for cId, c of connectors 62 | 63 | # recalculates list of chunks, neighbors, etc after a remap 64 | update: -> 65 | @chunkList = [] 66 | @chunkList.push chunk for chunk in @assignment if @assignment? 67 | 68 | # TODO: maybe add all regions in range, rather than bordering neighbors 69 | neighbors = {} 70 | checkNeighbor = (x, z) => 71 | regionId = @world.map.get(x, z)?.region 72 | if regionId? and regionId != @regionId and not neighbors[regionId]? 73 | neighbors[regionId] = true 74 | 75 | for chunk in @chunkList 76 | checkNeighbor chunk.x+1, chunk.z 77 | checkNeighbor chunk.x-1, chunk.z 78 | checkNeighbor chunk.x, chunk.z+1 79 | checkNeighbor chunk.x, chunk.z-1 80 | 81 | @neighbors = [] 82 | for regionId of neighbors 83 | @neighbors.push _.clone @world.servers[regionId] 84 | 85 | module.exports = Region -------------------------------------------------------------------------------- /lib/models/gridCollection.coffee: -------------------------------------------------------------------------------- 1 | Model = require './model' 2 | 3 | # a general class for storing things on a static 2d grid (1 model per cell) 4 | class GridCollection extends Model 5 | constructor: (cells) -> 6 | @rows = {} 7 | @cols = {} 8 | 9 | if cells? 10 | for x, col of cells 11 | @update x, 'x' 12 | @update y, 'y' for y of col 13 | 14 | else @width = @height = 0 15 | 16 | @cells = cells?.cells or cells or {} 17 | 18 | getCol: (x) -> 19 | col = @cells[x] 20 | col = @cells[x] = {} if not col? 21 | col 22 | 23 | set: (model, x, y) -> 24 | col = @getCol(x) 25 | if not col[y]? 26 | @update x, 'x' 27 | @update y, 'y' 28 | 29 | col[y] = model 30 | 31 | get: (x, y) -> 32 | @cells[x]?[y] 33 | 34 | remove: (x, y) -> 35 | # delete cell 36 | if y? 37 | col = @cells[x] 38 | if col? 39 | model = @cells[x][y] 40 | delete @cells[x][y] 41 | model 42 | 43 | # delete row/column 44 | else 45 | delete @cells[x] 46 | 47 | @update x, 'x', true 48 | @update y, 'y', true 49 | 50 | # based on the coordinate and axis we are adding/removing an item at, 51 | # update the min/max/size 52 | update: (value, axis, remove) -> 53 | value = +value 54 | axis = axis.toUpperCase() 55 | 56 | if not remove 57 | @['min'+axis] = value if not @['min'+axis] or @['min'+axis] > value 58 | @['max'+axis] = value if not @['max'+axis] or @['max'+axis] < value 59 | 60 | if axis == 'X' 61 | sizeKey = 'width' 62 | dimensionKey = 'cols' 63 | else if axis == 'Y' 64 | sizeKey = 'height' 65 | dimensionKey = 'rows' 66 | 67 | @[sizeKey] = @['max'+axis] - @['min'+axis] + 1 68 | 69 | if not remove 70 | if not @[dimensionKey][value]? then @[dimensionKey][value] = 1 71 | else @[dimensionKey][value]++ 72 | 73 | else 74 | # find new min/max if neccessary 75 | if --@[dimensionKey][value] <= 0 76 | min = true if value == @['min'+axis] 77 | max = true if value == @['max'+axis] 78 | 79 | if min or max 80 | if --@[sizeKey] <= 0 81 | @['min'+axis] = @['max'+axis] = undefined 82 | 83 | else 84 | if min 85 | for i in [value+1..@['max'+axis]] 86 | if @[dimensionKey][i] 87 | @['min'+axis] = i 88 | break 89 | else if max 90 | for i in [value-1..@['min'+axis]] 91 | if @[dimensionKey][i] 92 | @['max'+axis] = i 93 | break 94 | 95 | @[sizeKey] = @['max'+axis] - @['min'+axis] + 1 96 | 97 | module.exports = GridCollection -------------------------------------------------------------------------------- /lib/controllers/server/inventory.coffee: -------------------------------------------------------------------------------- 1 | async = require 'async' 2 | _ = require 'underscore' 3 | 4 | # takes in an item or an array of items and converts to send in a packet 5 | toSlot = (input, cb) -> 6 | return cb null, {id: -1} if not input 7 | 8 | if Array.isArray input 9 | tasks = [] 10 | for item in input 11 | ((item) -> tasks.push (cb2) -> toSlot item, cb2)(item) 12 | async.parallel tasks, cb 13 | 14 | else 15 | cb null, input 16 | 17 | sendInventory = -> 18 | toSlot @inventory, (err, items) => @send 0x68, {windowId: 0, items: items} 19 | 20 | sendSlot = (slotId) -> 21 | toSlot @inventory[slotId], (err, item) => @send 0x67, {windowId: 0, slot: slotId, item: item} 22 | 23 | # TODO: survival inventory 24 | module.exports = (config) -> 25 | @on 'join', (e, player) => 26 | player.inventory = if player.storage.inventory then _.clone(player.storage.inventory) else [] 27 | player.sendInventory = sendInventory.bind player 28 | player.sendSlot = sendSlot.bind player 29 | 30 | player.on 'ready', player.sendInventory 31 | 32 | player.on 0x6b, (e, packet) -> 33 | if 0 <= packet.slot <= 44 34 | packet.item = null if packet.item.id == -1 35 | player.inventory[packet.slot] = packet.item 36 | 37 | # on item drop (q) 38 | player.on 0xe, (e, packet) -> 39 | if packet.status == 4 40 | # TODO: use inventory controller remove method when implemented 41 | player.inventory[player.heldSlot+36] = null 42 | player.sendSlot player.heldSlot+36 43 | 44 | # TODO: finish the item entity code below 45 | ### 46 | # TODO: make a utility function somewhere to get facing component vector 47 | magnitude = 1 48 | 49 | yaw = player.position.yaw % 360 50 | yaw += 360 if yaw < 0 51 | yaw = 360 - yaw 52 | 53 | pitch = player.position.pitch % 360 54 | pitch += 360 if pitch < 0 55 | pitch = 360 - pitch 56 | 57 | vX = magnitude * Math.sin yaw * Math.PI / 180 58 | vY = magnitude * Math.sin pitch * Math.PI / 180 59 | vZ = magnitude * Math.cos yaw * Math.PI / 180 60 | 61 | player.send 0x17, 62 | entityId: Math.floor Math.random() * 0xfffffff 63 | type: 2 64 | x: Math.floor player.position.x * 32 65 | y: Math.floor (player.position.y + 1.3) * 32 66 | z: Math.floor player.position.z * 32 67 | yaw: 0 68 | pitch: 0 69 | objectData: 70 | intField: 1 71 | velocityX: Math.floor vX * 1024 72 | velocityY: Math.floor vY * 1024 73 | velocityZ: Math.floor vZ * 1024 74 | ### 75 | 76 | @on 'quit', (e, player) => 77 | player.storage.inventory = player.inventory 78 | -------------------------------------------------------------------------------- /lib/controllers/server/neighbors.coffee: -------------------------------------------------------------------------------- 1 | _ = require 'underscore' 2 | MapCollection = require '../../models/mapCollection' 3 | Player = require '../../models/server/player' 4 | 5 | module.exports = -> 6 | 7 | connectNeighbors = (region) => 8 | # TODO: disconnect from neighbors when not needed 9 | for neighbor in region.neighbors 10 | do (neighbor) => 11 | connect = => 12 | @connect neighbor, (server) => 13 | neighbor.connection = server.connection 14 | 15 | if neighbor.id > @id and not neighbor.connection? 16 | setTimeout connect, 2000 17 | else connect() 18 | 19 | @on 'region:after', (e, region, options) => 20 | region.globalPlayers = new MapCollection 21 | indexes: [{key: 'username', replace: true}] 22 | cellSize: 16 23 | 24 | broadcastPlayer = (player, connector) -> 25 | p = _.pick player, 'username', 'position', 'id' 26 | p.connector = _.omit player.connector, 'connection' if connector 27 | for neighbor in region.neighbors 28 | if neighbor.connection? 29 | neighbor.connection.emit 'player', region.world.id, p 30 | 31 | broadcastRemovePlayer = (player) -> 32 | p = _.pick player, 'username', 'position', 'id' 33 | for neighbor in region.neighbors 34 | if neighbor.connection? 35 | neighbor.connection.emit 'removePlayer', region.world.id, p 36 | 37 | connectNeighbors region 38 | 39 | region.players.on 'insert:after', (e, player) => 40 | broadcastPlayer player, true 41 | 42 | broadcastInterval = setInterval -> 43 | broadcastPlayer player 44 | , 5000 45 | 46 | player.on 'leave:after', -> 47 | clearInterval broadcastInterval 48 | broadcastRemovePlayer player 49 | 50 | region.on 'remap:after', (e) => 51 | connectNeighbors region 52 | broadcastPlayer player, true for player in region.players.models 53 | 54 | @on 'peer.server', (e, server, connection) => 55 | for region in @regions.models 56 | for neighbor in region.neighbors 57 | if neighbor.id == server.id 58 | neighbor.connection = connection 59 | break 60 | 61 | connection.on 'player', (regionId, p) => 62 | region = @regions.get 'world.id', regionId 63 | player = region.globalPlayers.get p.id 64 | 65 | if not player? 66 | @connect p.connector, (connector) => 67 | player = new Player p 68 | player.connector = connector 69 | 70 | region.globalPlayers.insert player 71 | 72 | else if not region.players.get p.id 73 | _.extend player, p 74 | player.emit 'move' 75 | 76 | connection.on 'removePlayer', (regionId, p) => 77 | region = @regions.get 'world.id', regionId 78 | player = region.globalPlayers.get p.id 79 | region.globalPlayers.remove p.id if player? -------------------------------------------------------------------------------- /lib/controllers/server/snake.coffee: -------------------------------------------------------------------------------- 1 | Map = require '../../models/server/map' 2 | _ = require 'underscore' 3 | 4 | LENGTH_INCREMENT = 10 5 | SPEED_INCREMENT = 4 6 | MARGIN = 20 7 | 8 | module.exports = -> 9 | @on 'join:after', (e, player) => 10 | player.on 'command.snake', (e) => 11 | player.enableKeys() if not player.keysEnabled 12 | 13 | # TODO: use inventory controller function for item-giving 14 | player.send 0x67, 15 | windowId: 0 16 | slot: 36 17 | item: 18 | id: 358 19 | itemCount: 1 20 | itemDamage: 1337 21 | nbtData: new Buffer 0 22 | player.send 0x10, 23 | slotId: 0 24 | 25 | map = new Map 1337 26 | snake = [{x: 64, y: 64}] 27 | add = LENGTH_INCREMENT 28 | direction = 0 29 | apple = {} 30 | 31 | updateFps = 14 32 | drawFps = 16 33 | 34 | updateTimer = null 35 | drawTimer = null 36 | 37 | draw = -> 38 | map.sendTo player 39 | 40 | update = -> 41 | head = _.clone snake[snake.length-1] 42 | 43 | if direction == 0 then head.y-- 44 | else if direction == 1 then head.x-- 45 | else if direction == 2 then head.y++ 46 | else if direction == 3 then head.x++ 47 | 48 | for point in snake 49 | return stop() if point.x == head.x and point.y == head.y 50 | return stop() if head.x < 0 or head.x > 127 or head.y < 0 or head.y > 127 51 | 52 | for point in snake 53 | if point.x == apple.x and point.y == apple.y 54 | add += LENGTH_INCREMENT 55 | updateFps += SPEED_INCREMENT 56 | restartTimer() 57 | placeApple() 58 | 59 | snake.push head 60 | if add > 0 then add-- 61 | else 62 | erase = snake.shift() 63 | map.setPixel 0, erase.x, erase.y 64 | 65 | map.setPixel 44, head.x, head.y 66 | 67 | placeApple = -> 68 | apple.x = MARGIN + Math.floor Math.random() * (128 - MARGIN) 69 | apple.y = MARGIN + Math.floor Math.random() * (128 - MARGIN) 70 | 71 | collision = false 72 | for point in snake 73 | placeApple() if point.x == apple.x and point.y == apple.y 74 | 75 | map.setPixel 18, apple.x, apple.y 76 | 77 | startTimer = -> updateTimer = setInterval update, 1000 / updateFps 78 | stopTimer = -> clearInterval updateTimer 79 | restartTimer = -> stopTimer(); startTimer() 80 | 81 | start = -> 82 | placeApple() 83 | startTimer() 84 | map.sendTo player, true 85 | drawTimer = setInterval draw, 1000 / drawFps 86 | 87 | stop = -> 88 | stopTimer() 89 | clearInterval drawTimer 90 | 91 | player.on 'key.w', -> direction = 0 if direction != 2 92 | player.on 'key.a', -> direction = 1 if direction != 3 93 | player.on 'key.s', -> direction = 2 if direction != 0 94 | player.on 'key.d', -> direction = 3 if direction != 1 95 | 96 | start() 97 | -------------------------------------------------------------------------------- /lib/controllers/server/players.coffee: -------------------------------------------------------------------------------- 1 | Player = require '../../models/server/player' 2 | Collection = require '../../models/collection' 3 | _ = require 'underscore' 4 | 5 | PLAYER_ENTITY_PREFIX = 1 << 28 6 | 7 | module.exports = (config) -> 8 | @players = new Collection [], indexes: ['username'] 9 | 10 | getPlayer = (fn) => 11 | return (id) => 12 | player = @players.get id 13 | args = Array::slice.call arguments, 1 14 | args.splice 0, 0, player 15 | fn.apply @, args if player? 16 | 17 | @on 'peer.connector', (e, connector, connection) => 18 | connection.on 'join', (player, state) => 19 | player.connector = connector 20 | player = new Player player 21 | 22 | if @players.get('username', player.username)? 23 | player.kick "Someone named '#{player.username}' is already connected." 24 | return 25 | 26 | @players.insert player 27 | @emit 'join', player, state 28 | 29 | player.on 'leave:after', (e) => 30 | @players.remove player 31 | 32 | connection.on 'quit', getPlayer (player) => 33 | player.emit 'leave' 34 | player.emit 'quit' if not player.kicked 35 | 36 | connection.on 'data', getPlayer (player, id, data) => 37 | player.emit 'data', id, data 38 | player.emit id, data 39 | 40 | @on 'join:before', (e, player, options) => 41 | if not options.handoff?.transparent 42 | @info "#{player.username} joined (connector:#{player.connector.id})" 43 | else 44 | @debug "#{player.username} joined (handoff) (connector:#{player.connector.id})" 45 | 46 | if not player.entityId? 47 | player.entityId = PLAYER_ENTITY_PREFIX | Math.floor Math.random() * 0xfffffff 48 | 49 | ready = -> 50 | player.emit 'ready' 51 | onReady = -> 52 | player.off 0xa, onReady 53 | player.off 0xb, onReady 54 | player.off 0xc, onReady 55 | player.off 0xd, onReady 56 | setTimeout ready, config.readyDelay or 250 57 | player.on 0xa, onReady 58 | player.on 0xb, onReady 59 | player.on 0xc, onReady 60 | player.on 0xd, onReady 61 | 62 | @on 'join:after', (e, player, options) => 63 | worldMeta = 64 | levelType: 'flat' 65 | gameMode: 1 66 | dimension: 0 67 | difficulty: 0 68 | maxPlayers: 64 69 | worldHeight: 256 70 | _.extend worldMeta, player.region.world.meta if player.region.world.meta? 71 | 72 | # player just joined 73 | if not options.handoff 74 | worldMeta.entityId = player.entityId 75 | player.send 0x1, worldMeta 76 | 77 | # player was handed off 78 | else 79 | # transparent handoff 80 | if options.handoff.transparent 81 | # TODO: do server handoff stuff 82 | 83 | # hard handoff 84 | else 85 | # change dimension, then go back in order to make sure client unloads everything 86 | fakeWorldMeta = _.clone worldMeta 87 | fakeWorldMeta.dimension++ 88 | fakeWorldMeta.dimension = 0 if fakeWorldMeta.dimension > 1 89 | player.send 0x9, fakeWorldMeta 90 | player.send 0x9, worldMeta 91 | 92 | player.on 'ready:after', => 93 | player.message "§aNow connected to server:#{@id}" 94 | 95 | @on 'update:before', (e, data) => 96 | data.players = @players.length 97 | -------------------------------------------------------------------------------- /lib/controllers/master/db.coffee: -------------------------------------------------------------------------------- 1 | mongodb = require 'mongodb' 2 | Db = mongodb.Db 3 | 4 | convertBuffers = (doc) -> 5 | if doc instanceof Array 6 | convertBuffers d for d in doc 7 | 8 | else 9 | for k, v of doc 10 | if typeof v == 'object' and v? 11 | if v._bsontype == 'Binary' then doc[k] = v.buffer 12 | else convertBuffers v 13 | 14 | module.exports = (config) -> 15 | Db.connect config.database, (err, db) => 16 | return @error "Error connecting to database: #{err}" if err 17 | @info 'Connected to database' 18 | 19 | # TODO: make sure calling db.collection every query isn't too slow 20 | @db = 21 | find: (collectionName, query, fields, options, cb) => 22 | cb = arguments[arguments.length-1] if typeof arguments[arguments.length-1] == 'function' 23 | collection = db.collection collectionName 24 | collection.find(query, fields, options).toArray (err, doc) -> 25 | convertBuffers doc; cb err, doc 26 | 27 | findOne: (collectionName, query, fields, options, cb) => 28 | cb = arguments[arguments.length-1] if typeof arguments[arguments.length-1] == 'function' 29 | collection = db.collection collectionName 30 | collection.findOne query, fields, options, (err, doc) -> 31 | convertBuffers doc; cb err, doc 32 | 33 | count: (collectionName, query, options, cb) => 34 | cb = arguments[arguments.length-1] if typeof arguments[arguments.length-1] == 'function' 35 | collection = db.collection collectionName 36 | collection.count query, options, cb 37 | 38 | insert: (collectionName, docs, options, cb) => 39 | cb = arguments[arguments.length-1] if typeof arguments[arguments.length-1] == 'function' 40 | options = options or {} 41 | options.safe = true if not options.safe? 42 | collection = db.collection collectionName 43 | collection.insert docs, options, cb 44 | 45 | update: (collectionName, crtiteria, objNew, options, cb) => 46 | cb = arguments[arguments.length-1] if typeof arguments[arguments.length-1] == 'function' 47 | options = options or {} 48 | options.safe = true if not options.safe? 49 | collection = db.collection collectionName 50 | collection.update crtiteria, objNew, options, cb 51 | 52 | remove: (collectionName, selector, options, cb) => 53 | cb = arguments[arguments.length-1] if typeof arguments[arguments.length-1] == 'function' 54 | options = options or {} 55 | options.safe = true if not options.safe? 56 | collection = db.collection collectionName 57 | collection.remove crtiteria, objNew, options, cb 58 | 59 | ensureIndex: (collectionName, keys, options, cb) => 60 | cb = arguments[arguments.length-1] if typeof arguments[arguments.length-1] == 'function' 61 | collection = db.collection collectionName 62 | collection.ensureIndex keys, options, cb 63 | 64 | # TODO: add other methods if needed 65 | 66 | # listen for peer db requests 67 | @on 'peer', (e, peer, connection) => 68 | for name, method of @db 69 | ((name, method) => 70 | connection.respond 'db.'+name, (res) => 71 | args = Array::slice.call arguments, 1 72 | args.push res 73 | method.apply @, args 74 | )(name, method) 75 | 76 | @emit 'db.ready' -------------------------------------------------------------------------------- /lib/controllers/master/regions.coffee: -------------------------------------------------------------------------------- 1 | _ = require 'underscore' 2 | 3 | module.exports = (config) -> 4 | # assign servers to worlds, map chunks to them, then notify servers of mappings 5 | @mapRegions = => 6 | # TODO: handle more than one world 7 | #for world in @worlds.models 8 | world = @worlds.get 0 9 | world.remap @peers.servers.length 10 | 11 | world.servers = [] 12 | for server in @peers.servers.models 13 | world.servers.push _.pick(server, 'id', 'address', 'type') 14 | 15 | options = {} 16 | remapDelay = if config.remapDelay? then config.remapDelay else 10 * 1000 17 | options.start = Date.now() + remapDelay 18 | 19 | for region, i in world.regions 20 | # TODO: figure out how servers should be assigned to worlds 21 | server = @peers.servers.get i 22 | @info "assigning region #{world.id}.#{i} to server:#{server.id}" 23 | 24 | # region options: 25 | # regionId: the id of this region (0-indexed) 26 | # world: info about the world this region is a part of 27 | # assignment: an array of the chunks in this region (in the format [{x: x, z: z}, ...]) 28 | 29 | # world options 30 | # id: the id of the world this region is in (a string) 31 | # map: a GridCollection of the assigned chunks 32 | # servers: an array of the servers hosting the regions in this world, ordered by the regionId they are assigned to 33 | # persistent: whether or not this is a persistent world (and should be loaded from disk/saved to db/etc) 34 | # meta: an object that contains the level type/dimension/etc. settings 35 | # generator: an object that contains the chunk generator type and options to use 36 | # storage: an object that contains the chunk storage type and options 37 | # size: the size limit of the world, either a number, or an object like {width: x, height: x} 38 | # pregen: whether or not to pregenerate all chunks (size must be defined) 39 | # static: whether or not to expand to unmapped chunks (servers should only load assigned chunks) 40 | 41 | server.connection.emit 'region', { 42 | regionId: i 43 | world: world 44 | assignment: region 45 | }, options 46 | 47 | resetTimer = => 48 | clearInterval @remapTimer if @remapTimer? 49 | @remapTimer = setInterval @mapRegions, config.remapInterval or 4 * 60 * 1000 50 | 51 | remapTimeout = null 52 | remap = => 53 | @mapRegions() 54 | resetTimer() 55 | remapTimeout = null 56 | 57 | @on 'peer.server:before', (e, server, connection) => 58 | server.regions = [] 59 | @on 'peer.server:after', (e, server, connection) => 60 | remapTimeout = setTimeout remap, 2000 if not remapTimeout? 61 | connection.on 'disconnect', remap 62 | 63 | @on 'peer.server.update:after', (e, server, stats) => 64 | for region in stats.regions 65 | world = @worlds.get region.worldId 66 | 67 | if world? 68 | for x, col of region.chunks 69 | for z, chunk of col 70 | c = world.getChunk(x, z) 71 | _.extend c, chunk 72 | c.players = c.players or 0 73 | 74 | setInterval => 75 | worlds = {} 76 | 77 | for server in @peers.servers.models 78 | for region in server.stats.regions 79 | worlds[region.worldId] = 0 if not worlds[region.worldId]? 80 | worlds[region.worldId] += region.players 81 | 82 | for worldId, players of worlds 83 | world = @worlds.get worldId 84 | world.players = players 85 | , 10 * 1000 -------------------------------------------------------------------------------- /lib/component.coffee: -------------------------------------------------------------------------------- 1 | os = require 'os' 2 | sock = require 'sock' 3 | EventStack = require './eventstack' 4 | Collection = require './models/collection' 5 | 6 | class Component extends EventStack 7 | constructor: (@config, control, master) -> 8 | super() 9 | 10 | @peers = new Collection 11 | @peers.connectors = new Collection 12 | @peers.servers = new Collection 13 | 14 | # listen for control connections from peers 15 | @control = sock.listen control 16 | @control.on 'connection', @onConnection 17 | 18 | #if a master is specified, connect to it 19 | @master = sock.connect master if master? 20 | 21 | log: (level, message) => @emit 'log', level, message 22 | debug: (message) => @log 'debug', message 23 | info: (message) => @log 'info', message 24 | warn: (message) => @log 'warn', message 25 | error: (message) => @log 'error', message 26 | 27 | use: (module) => 28 | args = [@config] 29 | 30 | if typeof module == 'function' then module.apply @, args 31 | else if Array.isArray module then m.apply @, args for m in module 32 | 33 | start: -> 34 | # tell the master we are ready 35 | @master.request 'init', 36 | type: @type 37 | port: @control.port, 38 | (@id) => 39 | @emit 'ready' 40 | 41 | # send stats to master periodically 42 | lastUpdate = 0 43 | updateMaster = => 44 | data = 45 | loadavg: os.loadavg() 46 | uptime: os.uptime() 47 | totalmem: os.totalmem() 48 | freemem: os.freemem() 49 | cpus: os.cpus().length 50 | @emit 'update', data, lastUpdate 51 | @master.emit 'update', data 52 | lastUpdate = Date.now() 53 | 54 | updateMaster() 55 | @updateMasterInterval = setInterval updateMaster, 10 * 1000 56 | 57 | onConnection: (connection) => 58 | # when a peer connects, wait for a 'init' request 59 | connection.respond 'init', (res, options) => 60 | peer = options or {} 61 | peer.connection = connection 62 | peer.address = "#{connection.remoteAddress}:#{peer.port}" 63 | 64 | # add peer to collections 65 | @peers.insert peer 66 | @peers[options.type+'s'].insert peer 67 | 68 | @info "incoming connection from #{options.type}:#{peer.id} (#{peer.address})" 69 | 70 | # answer peer with its id 71 | res peer.id 72 | 73 | @emit 'peer', peer, connection 74 | @emit 'peer.'+options.type, peer, connection 75 | 76 | connection.on 'disconnect', => 77 | @peers.remove peer 78 | @peers[options.type+'s'].remove peer 79 | 80 | @info "#{options.type}:#{peer.id} disconnected" 81 | 82 | # connect to a peer (not master), or get the connection if already connected 83 | connect: (p, cb) -> 84 | if typeof cb != 'function' then cb = -> 85 | 86 | peer = @peers.get p.id 87 | 88 | # not connected, make a new connection 89 | if not peer? 90 | peer = p 91 | peer.connection = sock.connect peer.address 92 | 93 | # make an 'init' request so peer will handle connection 94 | peer.connection.request 'init', 95 | type: @type 96 | id: @id 97 | port: @control.port, 98 | => 99 | @peers.insert peer 100 | @peers[p.type+'s'].insert peer 101 | @emit 'connect', peer 102 | @emit 'connect.'+p.type, peer 103 | @emit 'peer', peer, peer.connection 104 | @emit 'peer.'+p.type, peer, peer.connection 105 | 106 | cb peer 107 | 108 | # already connected, return the connection 109 | else cb peer 110 | 111 | module.exports = Component -------------------------------------------------------------------------------- /bin/redstone: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env coffee 2 | 3 | require 'coffee-script' 4 | program = require 'commander' 5 | cluster = require 'cluster' 6 | os = require 'os' 7 | 8 | program 9 | .version('0.0.0') 10 | .option('-c, --connector', 'Run a connector instance') 11 | .option('-s, --server', 'Run a server instance') 12 | .option('-m, --master [master]', 'Run a master instance, or specify a master to connect to') 13 | .option('--control ', 'Changes the port used for control protocol') 14 | .option('-S, --suppress', 'Supress logging') 15 | .option('-v, --verbose', 'Log more detailed stuff') 16 | .option('-C, --chat', 'Log chat') 17 | .option('--config [file]', 'Loads the specified config file', '../config') 18 | .parse process.argv 19 | 20 | if program.config? then config = require program.config 21 | else config = {} 22 | 23 | 24 | components = {} 25 | components.connector = program.connector if program.connector == true 26 | components.server = program.server if program.server == true 27 | components.master = program.master if program.master == true 28 | 29 | # if no components specified, run them all 30 | unless components.connector or components.server or components.master 31 | components.connector = components.server = components.master = true 32 | 33 | # check if more than one component is running 34 | componentCount = Number(components.connector) + Number(components.server) + Number(components.master) 35 | multipleComponents = componentCount > 1 36 | 37 | config.control = Number (program.control or config.control or 8000) 38 | config.master = program.master or config.master 39 | 40 | # we either need a master to connect to, or we should run a local master 41 | unless config.master or components.master 42 | console.log 'You must either specify a master to connect to or run a master instance' 43 | program.help() 44 | 45 | 46 | # logging 47 | winston = require 'winston' 48 | levels = 49 | chat: -1 50 | debug: 0 51 | info: 1 52 | warn: 2 53 | error: 3 54 | colors = 55 | chat: 'green' 56 | debug: 'white' 57 | info: 'cyan' 58 | warn: 'yellow' 59 | error: 'red' 60 | transports = [] 61 | level = 62 | if program.suppress then 'error' 63 | else if program.chat then 'chat' 64 | else if program.verbose then 'debug' 65 | else 'info' 66 | transports.push new winston.transports.Console 67 | colorize: true 68 | level: level 69 | logger = new winston.Logger transports: transports, levels: levels 70 | winston.addColors colors 71 | 72 | control = process.env.CONTROL or config.control 73 | 74 | startComponents = -> 75 | if components.server 76 | if cluster.isMaster and os.platform().indexOf('win') != 0 77 | cpus = os.cpus().length 78 | cluster.fork(CONTROL: control++) for i in [0...cpus] 79 | 80 | else 81 | logger.info 'Initializing server' 82 | Server = require '../lib/server' 83 | server = new Server config, control++, config.master 84 | server.on 'log', (e, level, message) -> 85 | logger.log level, (if multipleComponents then '[server] ' else '') + message 86 | server.start() 87 | 88 | 89 | if components.connector 90 | if cluster.isMaster and os.platform().indexOf('win') != 0 91 | cpus = os.cpus().length 92 | cluster.fork(CONTROL: control++) for i in [0...cpus] 93 | 94 | else 95 | logger.info 'Initializing connector' 96 | Connector = require '../lib/connector' 97 | connector = new Connector config, control++, config.master 98 | connector.on 'log', (e, level, message) -> 99 | logger.log level, (if multipleComponents then '[connector] ' else '') + message 100 | connector.start() 101 | 102 | if components.master 103 | logger.info 'Initializing master' 104 | 105 | Master = require '../lib/master' 106 | 107 | c = control++ 108 | config.master = 'localhost:'+c 109 | 110 | master = new Master config, c 111 | master.on 'log', (e, level, message) -> 112 | logger.log level, (if multipleComponents then '[master] ' else '') + message 113 | 114 | master.start() 115 | 116 | setTimeout startComponents, 2000 117 | else 118 | startComponents() 119 | 120 | process.on 'uncaughtException', (err) -> 121 | logger.log 'error', err.stack -------------------------------------------------------------------------------- /lib/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Redstone Control Panel 5 | 24 | 25 | 26 |

Redstone Control Panel

27 |
28 |
29 |

Worlds

30 |

31 |
32 |
33 |

Servers

34 |

35 |
36 | 37 | 133 | 134 | -------------------------------------------------------------------------------- /lib/controllers/server/regions.coffee: -------------------------------------------------------------------------------- 1 | Region = require '../../models/server/region' 2 | Collection = require '../../models/collection' 3 | GridCollection = require '../../models/gridCollection' 4 | _ = require 'underscore' 5 | 6 | module.exports = -> 7 | s = @ 8 | 9 | handoff = (server, options) -> 10 | @emit 'leave' 11 | @message "§aLeaving server:#{s.id}" 12 | @_send 'handoff', server, @toJson(), options 13 | 14 | @regions = new Collection indexes: [{key: 'world.id', replace: true}, 'id'] 15 | @regions.generateId = (region) -> "#{region.world.id}.#{region.regionId}" 16 | 17 | @master.on 'region', (r, options) => 18 | region = @regions.get 'world.id', r.world.id 19 | options = options or {} 20 | 21 | r.world.map = new GridCollection r.world.map 22 | 23 | delay = options.delay = options.start - Date.now() if options.start? 24 | 25 | if not region? 26 | region = new Region r 27 | @regions.insert region 28 | @info "starting region #{region.id}" 29 | @emit 'region', region, options 30 | region.start() 31 | 32 | else 33 | # calculate diff of chunks inside region 34 | options.chunks = 35 | add: [] 36 | remove: [] 37 | keep: [] 38 | 39 | chunkGrid = new GridCollection 40 | 41 | for chunk in region.chunkList 42 | chunkGrid.set chunk, chunk.x, chunk.z 43 | newRegion = r.world.map.get(chunk.x, chunk.z)?.region 44 | if newRegion != r.regionId 45 | chunk.region = newRegion 46 | options.chunks.remove.push chunk 47 | else 48 | options.chunks.keep.push chunk 49 | for chunk in r.assignment 50 | options.chunks.add.push chunk if not chunkGrid.get(chunk.x, chunk.z)? 51 | 52 | # do stuff that needs to happen before actual remap (e.g. saving/loading) 53 | @info "preparing to remap region #{region.id}" 54 | region.emit 'preRemap', r, options 55 | 56 | # make the remap active 57 | remap = => 58 | @info "remapping region #{region.id}" 59 | _.extend region, r 60 | 61 | # in chunks that we aren't handling anymore, 62 | # handoff the players to their new server 63 | for chunk in options.chunks.remove 64 | if chunk.players 65 | newServer = region.world.servers[chunk.region] 66 | players = region.players.grid[chunk.x][chunk.z].models 67 | 68 | for player in players 69 | if player? 70 | player.handoff newServer, 71 | handoff: transparent: true 72 | storage: player.storage 73 | 74 | # recalculate who our neighbors are and reset some stuff 75 | region.update() 76 | 77 | region.emit 'remap' 78 | 79 | setTimeout remap, delay 80 | 81 | @on 'join:before', (e, player) => 82 | region = player.region = @regions.get 'world.id', player.storage.world 83 | region.players.insert player 84 | 85 | @debug "#{player.username} added to region:#{region.id}" 86 | 87 | player.handoff = handoff.bind player 88 | 89 | player.on 'moveChunk:after', (e, x, z) => 90 | world = player.region.world 91 | chunk = world.map.get x, z 92 | 93 | if not chunk? 94 | @debug "#{player.username}/#{player.id} moved to an unmapped chunk" 95 | 96 | else if chunk.region != player.region.regionId 97 | neighbor = world.servers[chunk.region] 98 | @debug "handing off #{player.username}/#{player.id} to server:#{neighbor.id} (region #{chunk.region})" 99 | player.handoff neighbor, {handoff: {transparent: true}, storage: player.storage} 100 | 101 | player.on 'toJson', (e, json) -> 102 | delete json.region 103 | 104 | player.on 'leave:after', (e) => 105 | region = player.region 106 | region.players.remove player 107 | packet = entityIds: [player.entityId] 108 | region.send 0x1d, packet 109 | @debug "#{player.username} removed from region #{region.id}" 110 | 111 | @on 'update:before', (e, data) => 112 | data.regions = [] 113 | 114 | for region in @regions.models 115 | r = 116 | chunks: {} 117 | players: region.players.length 118 | regionId: region.regionId 119 | worldId: region.world.id 120 | 121 | for chunk in region.chunkList 122 | players = region.players.grid.get(chunk.x, chunk.z)?.length or 0 123 | if not chunk.players? or players != chunk.players 124 | obj = {} 125 | obj.players = players if players or chunk.players? 126 | 127 | col = r.chunks[chunk.x] 128 | col = r.chunks[chunk.x] = {} if not col? 129 | 130 | col[chunk.z] = obj 131 | chunk.players = players 132 | 133 | data.regions.push r 134 | -------------------------------------------------------------------------------- /lib/controllers/server/playerMovement.coffee: -------------------------------------------------------------------------------- 1 | _ = require 'underscore' 2 | 3 | packAngle = (degrees) -> 4 | degrees = degrees % 360 + if degrees < 0 then 360 else 0 5 | Math.floor (degrees - if degrees > 180 then 360 else 0) * (0xff / 360) 6 | 7 | updateChunkCoordinates = (player) -> 8 | player.chunkX = Math.floor player.position.x / 16 9 | player.chunkZ = Math.floor player.position.z / 16 10 | 11 | spawn = (options) -> 12 | if not options?.handoff? 13 | @send 0xd, @position 14 | 15 | packet = 16 | entityId: @entityId 17 | name: @username 18 | x: Math.floor @position.x * 32 19 | y: Math.floor @position.y * 32 20 | z: Math.floor @position.z * 32 21 | yaw: packAngle @position.yaw 22 | pitch: packAngle @position.pitch 23 | currentItem: 0 24 | metadata: [ 25 | {key: 0, type: 'byte', value: 0} 26 | {key: 8, type: 'int', value: 0} 27 | ] 28 | 29 | @region.send @position, {radius: 64, exclude: [@]}, 0x14, packet 30 | 31 | for p in @region.players.getRadius @, 64 32 | if p != @ 33 | @send 0x14, 34 | entityId: p.entityId 35 | name: p.username 36 | x: Math.floor p.position.x * 32 37 | y: Math.floor p.position.y * 32 38 | z: Math.floor p.position.z * 32 39 | yaw: packAngle p.position.yaw 40 | pitch: packAngle p.position.pitch 41 | currentItem: 0 42 | metadata: [ 43 | {key: 0, type: 'byte', value: 0} 44 | {key: 8, type: 'int', value: 0} 45 | ] 46 | 47 | module.exports = (config) -> 48 | @on 'join:before', (e, player, state) => 49 | if not player.position? 50 | player.position = 51 | if player.storage.position? then _.clone player.storage.position 52 | else 53 | x: 0 54 | y: 128 55 | z: 0 56 | yaw: 0 57 | pitch: 0 58 | player.position.stance = player.position.y + 1.8 59 | player.position.onGround = false 60 | 61 | updateChunkCoordinates player 62 | player.spawn = spawn.bind player 63 | 64 | setTimeout player.spawn, config.spawnDelay or 250, state 65 | 66 | @on 'join:after', (e, player, state) => 67 | emitMoving = -> player.emit 'moving' 68 | 69 | onMovement = (e, packet) -> 70 | d = player.positionDelta = _.clone player.position 71 | d[k] = (Number(packet[k]) - Number(v)) || 0 for k,v of d 72 | 73 | moved = Math.abs(d.x) > 0.01 or Math.abs(d.y) > 0.01 or Math.abs(d.z) > 0.01 74 | looked = d.yaw or d.pitch 75 | 76 | if moved or looked 77 | player.position[k] = Number(player.position[k]) + Number(v) for k,v of d 78 | player.position.onGround = Boolean player.position.onGround 79 | 80 | player.emit 'look', d if looked 81 | 82 | if moved 83 | if player.stopped 84 | player.stopped = false 85 | player.movingInterval = setInterval emitMoving, 1000 if not player.movingInterval 86 | player.emit 'start' 87 | player.emit 'move', d 88 | else if not player.stopped 89 | player.stopped = true 90 | clearInterval player.movingInterval 91 | player.movingInterval = null 92 | player.emit 'stop' 93 | 94 | player.on 'toJson', (e, json) -> 95 | delete json.movingInterval 96 | 97 | player.on 'ready:after', (e) -> 98 | player.on 0xb, onMovement 99 | player.on 0xc, onMovement 100 | player.on 0xd, onMovement 101 | 102 | player.on 'quit', (e) => 103 | # TODO: save position at other times, too 104 | player.storage.position = _.pick player.position, 'x', 'y', 'z', 'yaw', 'pitch' 105 | @emit 'quit', player 106 | @info "#{player.username} quit (connector:#{player.connector.id})" 107 | 108 | options = 109 | radius: 64 110 | exclude: [player] 111 | 112 | player.on 'look', (e, d) -> 113 | look = 114 | entityId: player.entityId 115 | yaw: packAngle player.position.yaw 116 | pitch: packAngle player.position.pitch 117 | headYaw = entityId: player.entityId, headYaw: look.yaw 118 | 119 | player.region.send player.position, options, 0x20, look 120 | player.region.send player.position, options, 0x23, headYaw 121 | 122 | player.on 'move:after', -> 123 | pos = 124 | entityId: player.entityId 125 | x: Math.round player.position.x * 32 126 | y: Math.round player.position.y * 32 127 | z: Math.round player.position.z * 32 128 | yaw: packAngle player.position.yaw 129 | pitch: packAngle player.position.pitch 130 | 131 | player.region.send player.position, options, 0x22, pos 132 | 133 | player.on 'move:after', -> 134 | lastX = player.chunkX 135 | lastZ = player.chunkZ 136 | 137 | updateChunkCoordinates player 138 | 139 | if lastX? and (lastX != player.chunkX or lastZ != player.chunkZ) 140 | player.emit 'moveChunk', player.chunkX, player.chunkZ 141 | -------------------------------------------------------------------------------- /lib/models/collection.coffee: -------------------------------------------------------------------------------- 1 | Model = require './model' 2 | 3 | get = (model, key, assert = true) -> 4 | key += '' 5 | keys = key.split '.' 6 | cursor = model 7 | 8 | for k, i in keys 9 | getKey = -> key = ''; key += keys[j] for j in [0..i]; key 10 | cursor = cursor[k] 11 | 12 | if i < keys.length - 1 13 | if not cursor? 14 | if assert then throw new Error "Model has no value at key '#{getKey()}'" 15 | else return 16 | 17 | if typeof cursor != 'object' 18 | if assert then throw new Error "Key #{getKey()} is not an object" 19 | else return 20 | 21 | cursor + '' 22 | 23 | remove = (array, model) -> 24 | i = array.indexOf model 25 | array.splice i, 1 if i != -1 26 | 27 | # index options: 28 | # sparse - only indexed if model has that value 29 | # duplicate - multiple models can be indexed by the same value (can't be used w/ override or replace) 30 | # override - overrides models indexed by the same value (can't be used w/ duplicate or replace) 31 | # replace - like override, but deletes old values (can't be used w/ override or duplicate) 32 | 33 | # TODO: make option to listen for changes to indexed values, and/or regenerate indexes 34 | 35 | class Collection extends Model 36 | constructor: (models, options) -> 37 | super() 38 | 39 | if not options? and not (models instanceof Array) 40 | options = models 41 | models = null 42 | 43 | models = models or [] 44 | 45 | indexes = if options?.indexes? then options.indexes else [] 46 | @_indexes = {} 47 | @createIndex index for index in indexes 48 | @createIndex 'id' if not @_indexes.id? 49 | 50 | @__defineGetter__ 'length', => @models.length 51 | 52 | @models = [] 53 | @insert model for model in models 54 | 55 | insert: (model) -> 56 | model.id = @generateId model if not model.id? 57 | @setIndex index, model for index of @_indexes 58 | @models.push model 59 | @emit 'insert', model 60 | 61 | get: (index, key) -> 62 | # if only one argument and it is a number, return models[key] 63 | # if it is not a number, default to 'id' index 64 | if not key? 65 | if typeof index == 'number' then return @models[index] 66 | else 67 | key = index 68 | index = 'id' 69 | 70 | @getIndex index, key 71 | 72 | remove: (index, key) -> 73 | # if index is an object, use it as the model 74 | if typeof index == 'object' 75 | return @removeModel index 76 | 77 | # if index is a number, use it as a numerical index (models[index]) 78 | else if typeof index == 'number' 79 | return @removeModel @models[index] 80 | 81 | # otherwise, remove all models indexed at index[key] (index defaults to id) 82 | else 83 | if not key? 84 | key = index 85 | index = 'id' 86 | 87 | models = @getIndex index, key 88 | index = @_indexes[index] 89 | 90 | if index.duplicate 91 | # delete the whole value array so we don't have to keep searching through it 92 | delete index.models[key] 93 | @removeModel model for model in models 94 | else 95 | @removeModel models 96 | 97 | return models 98 | 99 | removeModel: (model) -> 100 | remove @models, model 101 | 102 | for key, index of @_indexes 103 | value = get model, key, not index.sparse 104 | 105 | if index.duplicate 106 | arr = index.models[value] 107 | remove arr, model if arr? 108 | 109 | else delete index.models[value] 110 | 111 | @emit 'remove', model 112 | return model 113 | 114 | createIndex: (index) -> 115 | if typeof index == 'string' then index = {key: index} 116 | else if typeof index == 'object' 117 | throw new Error 'No key specified for index' if not index.key? 118 | throw new Error "Tried to create duplicate index '#{index.key}'" if @_indexes[index.key]? 119 | if +(index.duplicate or false) + +(index.override or false) + +(index.replace or false) > 1 120 | throw new Error "Cannot use 'duplicate', 'override', or 'replace' together" 121 | 122 | index.models = {} 123 | @_indexes[index.key] = index 124 | 125 | setIndex: (key, model) -> 126 | index = @_indexes[key] 127 | value = get model, index.key, not index.sparse 128 | 129 | if not value? or value == null 130 | throw new Error 'Model has no value at indexed key #{key}' if not index.sparse 131 | return 132 | 133 | if index.duplicate 134 | arr = index.models[value] 135 | arr = index.models[value] = [] if not arr? 136 | arr.push model if arr.indexOf(model) == -1 137 | else 138 | if index.models[value]? 139 | if index.replace 140 | @removeModel index.models[value] 141 | else if not index.override 142 | throw new Error "Duplicate indexed value (#{key} -> #{value})" 143 | index.models[value] = model 144 | 145 | getIndex: (index, key) -> 146 | index = @_indexes[index] 147 | throw new Error "Tried to lookup on nonexistent index '#{index}'" if not index? 148 | value = index.models[key] 149 | return [] if not value? and index.duplicate 150 | value 151 | 152 | generateId: (model) -> 153 | return model.id if model.id? 154 | while not id? or @_indexes.id.models[id]? 155 | id = Math.floor(Math.random() * 2821109907455).toString(36) 156 | id 157 | 158 | module.exports = Collection -------------------------------------------------------------------------------- /lib/controllers/server/chunks.coffee: -------------------------------------------------------------------------------- 1 | GridCollection = require '../../models/gridCollection' 2 | ChunkCollection = require '../../models/server/chunkCollection' 3 | async = require 'async' 4 | 5 | module.exports = (config) -> 6 | 7 | sendChunk = (x, z) -> 8 | @region.chunks.getChunk x, z, (err, chunk) => 9 | return @error err if err? 10 | chunk.toPacket {x: x, z: z}, (err, packet) => 11 | return @error err if err? 12 | @send 0x33, packet 13 | @loadedChunks.set chunk.lastUpdate, x, z 14 | 15 | sendChunks = -> 16 | initial = not @settings? 17 | 18 | maxViewDistance = config.viewDistance or 9 19 | multiplier = (5 - if not initial then @settings.viewDistance else 3) / 5 20 | viewDistance = Math.round multiplier * maxViewDistance 21 | 22 | chunkRate = 23 | if initial then 0 24 | else if config.chunkInterval? then config.chunkInterval 25 | else 10 26 | 27 | now = Date.now() 28 | 29 | # get list of in-range, unsent chunks 30 | chunks = [] 31 | for x in [-viewDistance+@chunkX..viewDistance+@chunkX] 32 | for z in [-viewDistance+@chunkZ..viewDistance+@chunkZ] 33 | lastUpdate = @loadedChunks.get x, z 34 | chunk = @region.chunks.chunks.get x, z 35 | mappedChunk = @region.world.map.get x, z 36 | localChunk = mappedChunk?.region == @region.regionId 37 | 38 | old = not lastUpdate or lastUpdate < chunk?.lastUpdate 39 | oob = @region.world.static and not mappedChunk 40 | 41 | if old and not oob 42 | d = Math.sqrt Math.pow(x - @chunkX, 2) + Math.pow(z - @chunkZ, 2) 43 | if d < viewDistance 44 | @region.chunkList.push {x: x, z: z} if not mappedChunk 45 | chunk.lastServed = now if chunk 46 | chunks.push x: x, z: z, d: d 47 | 48 | # sort chunks by distance 49 | chunks.sort (a, b) -> 50 | if a.d < b.d then -1 51 | else 1 52 | 53 | # send chunks 54 | tasks = [] 55 | for chunk in chunks 56 | do (chunk) => 57 | tasks.push (cb) => 58 | @sendChunk chunk.x, chunk.z 59 | 60 | done = -> cb null, true 61 | if chunkRate then setTimeout done, chunkRate 62 | else done() 63 | async.series tasks 64 | 65 | saveChunks = -> 66 | for chunk in @chunkList 67 | do (chunk) => 68 | @chunks.getChunk chunk.x, chunk.z, (err, c) => 69 | if not c.lastSave? or c.lastUpdate > c.lastSave 70 | @chunks.storeChunk chunk.x, chunk.z 71 | 72 | @on 'region:before', (e, region, options) => 73 | collectionOptions = {} 74 | 75 | if not region.static 76 | generator = require '../../generators/' + (region.world.generator?.type or 'superflat') 77 | collectionOptions.generator = generator region.world.generator?.options 78 | 79 | if region.world.persistent 80 | storage = require '../../storage/' + (region.world.storage?.type or 'simple') 81 | collectionOptions.storage = storage region.world.storage?.options or {path: "data/chunks/#{region.world.id}"} 82 | 83 | region.chunks = new ChunkCollection collectionOptions 84 | 85 | getChunks = -> 86 | # TODO: maybe we shouldn't always load all the chunks we are assigned? 87 | region.chunks.getChunk chunk.x, chunk.z for chunk in region.assignment 88 | if options.delay then setTimeout getChunks, options.delay / 2 89 | else getChunks() 90 | 91 | loadNeighborChunks = -> 92 | for x, col of region.chunks.chunks 93 | for z, chunk of col 94 | if region.world.map.get(x, z)?.region != region.regionId 95 | if Date.now() - chunk.lastServed >= (config.chunkUnloadDelay or 5 * 60 * 1000) 96 | region.chunks.unloadChunk x, z 97 | else 98 | # TODO: only load if updated 99 | region.chunks.loadChunk x, z 100 | region.loadTimer = setInterval loadNeighborChunks, config.chunkReloadInterval or 60 * 1000 101 | 102 | region.on 'preRemap:before', (e, r, options) -> 103 | loadChunks = -> 104 | region.chunks.loadChunk chunk.x, chunk.z for chunk in options.chunks.add 105 | setTimeout loadChunks, options.delay / 2 106 | region.chunks.storeChunk chunk.x, chunk.z for chunk in options.chunks.remove 107 | 108 | region.saveChunks = saveChunks.bind region 109 | region.saveTimer = setInterval region.saveChunks, config.saveInterval or 60 * 1000 110 | 111 | @on 'join:before', (e, player, options) => 112 | player.loadedChunks = new GridCollection player.loadedChunks 113 | player.sendChunk = sendChunk.bind player 114 | player.sendChunks = sendChunks.bind player 115 | 116 | @on 'join:after', (e, player) -> 117 | player.sendChunks() 118 | player.on 'ready:after', player.sendChunks 119 | player.on 'moveChunk:after', player.sendChunks 120 | 121 | player.on 'leave:before', -> 122 | now = Date.now() 123 | for chunk in player.region.chunkList 124 | player.loadedChunks.set now, chunk.x, chunk.z 125 | 126 | @on 'update:after', (e, data, lastUpdate) => 127 | for region, i in @regions.models 128 | r = data.regions[i] 129 | for chunk in region.chunkList 130 | do (chunk) => 131 | region.chunks.getChunk chunk.x, chunk.z, (err, c) => 132 | return @error err if err? 133 | if c.lastUpdate >= lastUpdate 134 | col = r.chunks[chunk.x] 135 | col = r.chunks[chunk.x] = {} if not col? 136 | updateChunk = col[chunk.z] 137 | updateChunk = col[chunk.z] = {} if not updateChunk? 138 | updateChunk.lastUpdate = c.lastUpdate -------------------------------------------------------------------------------- /lib/controllers/server/maps.coffee: -------------------------------------------------------------------------------- 1 | Map = require '../../models/server/map' 2 | 3 | colors = 4 | 4: r:89, g:125, b:39 5 | 5: r:109, g:153, b:48 6 | 6: r:127, g:178, b:56 7 | 8: r:174, g:164, b:115 8 | 9: r:213, g:201, b:140 9 | 10: r:247, g:233, b:163 10 | 12: r:117, g:117, b:117 11 | 13: r:144, g:144, b:144 12 | 14: r:167, g:167, b:167 13 | 16: r:180, g:0, b:0 14 | 17: r:220, g:0, b:0 15 | 18: r:255, g:0, b:0 16 | 20: r:112, g:112, b:180 17 | 21: r:138, g:138, b:220 18 | 22: r:160, g:160, b:255 19 | 24: r:117, g:117, b:117 20 | 25: r:144, g:144, b:144 21 | 26: r:167, g:167, b:167 22 | 28: r:0, g:87, b:0 23 | 29: r:0, g:106, b:0 24 | 30: r:0, g:124, b:0 25 | 32: r:180, g:180, b:180 26 | 33: r:220, g:220, b:220 27 | 34: r:255, g:255, b:255 28 | 36: r:115, g:118, b:129 29 | 37: r:141, g:144, b:158 30 | 38: r:164, g:168, b:184 31 | 40: r:129, g:74, b:33 32 | 41: r:157, g:91, b:40 33 | 42: r:183, g:106, b:47 34 | 44: r:79, g:79, b:79 35 | 45: r:96, g:96, b:96 36 | 46: r:112, g:112, b:112 37 | 48: r:45, g:45, b:180 38 | 49: r:55, g:55, b:220 39 | 50: r:64, g:64, b:255 40 | 52: r:73, g:58, b:35 41 | 53: r:89, g:71, b:43 42 | 54: r:104, g:83, b:50 43 | 44 | # make a hash table of best color fits for 6-bit color range 45 | colorMap = [] 46 | for i in [0...64] 47 | lowestDiff = Infinity 48 | code = null 49 | for colorCode, color of colors 50 | diff = 0 51 | diff += Math.abs color.r / 255 * 3 - ((i & 0x30) >> 4) 52 | diff += Math.abs color.g / 255 * 3 - ((i & 0xc) >> 2) 53 | diff += Math.abs color.b / 255 * 3 - (i & 0x3) 54 | if diff < lowestDiff 55 | lowestDiff = diff 56 | code = colorCode 57 | colorMap[i] = code 58 | 59 | toMapColor = (color) -> 60 | if typeof color == 'number' 61 | c = color 62 | color = 63 | r: (c & 0xff0000) >> 16 64 | g: (c & 0xff00) >> 8 65 | b: c & 0xff 66 | 67 | key = 0 68 | key |= Math.round(color.r / 255 * 3) << 4 69 | key |= Math.round(color.g / 255 * 3) << 2 70 | key |= Math.round color.b / 255 * 3 71 | colorMap[key] 72 | 73 | module.exports = -> 74 | map = new Map 75 | for col, x in rawImage 76 | for c, y in col 77 | map.setPixel toMapColor(c), x, y 78 | 79 | @on 'join:after', (e, player) -> 80 | player.on 'command.notch', (e) => 81 | # TODO: use inventory controller function for item-giving 82 | player.send 0x67, 83 | windowId: 0 84 | slot: 36 85 | item: 86 | id: 358 87 | itemCount: 1 88 | itemDamage: 0 89 | nbtData: new Buffer 0 90 | player.send 0x10, 91 | slotId: 0 92 | 93 | map.sendTo player, true 94 | 95 | # image data (notch's twitter avatar) 96 | rawImage = [[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16645629,13026745,6052693,1381138,854798,855054,855054,854798,854798,854798,3749689,13289672,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,15000018,2499878,1447195,855054,854798,854798,854798,854798,854798,854798,854798,854798,855054,1973021,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16053234,9801829,1447195,1447195,1249815,920590,4012586,13024890,15590544,15985044,15656081,15261325,12104049,3815209,854798,854798,1644570,15263719,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,7303023,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,14211032,2500139,1447194,1447194,1447194,920847,855054,1052176,2630944,6775365,12433014,15919507,14669448,15393167,15524496,11577709,1249553,855054,1841948,15000547,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,7303023,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16119285,1578778,1118228,1118229,1315607,1315607,920847,1644057,1709850,1775643,1775643,1775643,2696739,7696205,15787666,14801290,16182422,15195789,1578516,855054,2104864,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,0,0,16777215,16777215,4802889,3092271,9079434,16777215,16777215,16777215,16777215,13619151,13619151,16777215,16777215,16777215,16777215,7303023,0,1644825,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,11053224,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,15592941,1381402,920847,920847,986640,1118226,1381142,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1906972,7433035,15129997,15656081,15195789,1841687,855054,3091502,16645629,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,2039583,0,7303023,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,7303023,0,2039583,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,13619151,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,15263977,1841953,1249815,855054,920847,1052433,1710107,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1973021,10327908,14537863,13222268,1381395,920847,8289148,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,9408399,9408399,9408399,9408399,9408399,9408399,9408399,16777215,16777215,0,0,16777215,16777215,2039583,0,4079166,9408399,9408399,9408399,9408399,9408399,9408399,9408399,9408399,16777215,16777215,7303023,0,2039583,16777215,16777215,9408399,9408399,9408399,9408399,9408399,9408399,14013909,16777215,13619151,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16382457,3157813,1447195,855055,920847,920847,1907487,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,4933173,11380332,8157007,855054,1184019,14803168,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,0,0,0,0,0,0,0,16777215,16777215,0,0,16777215,16777215,2039583,0,0,0,0,0,0,0,0,0,0,16777215,16777215,7303023,0,2039583,16777215,16777215,0,0,0,0,0,0,10461087,16777215,13619151,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,6908268,1447195,1447194,920590,986384,1776156,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1907486,3420456,11906672,1776151,986640,3617332,16711422,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,0,0,0,0,0,0,0,16777215,16777215,0,0,16777215,16777215,2960685,986895,986895,986895,986895,986895,986895,0,0,986895,986895,16777215,16777215,7303023,0,2039583,16777215,16777215,0,0,0,0,0,0,10461087,16777215,13619151,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,12632258,1447195,1447194,1381400,986383,1512728,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775644,1841437,1775900,6051645,13353596,855054,855054,14934754,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,0,0,0,0,0,0,0,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,7303023,0,2039583,16777215,16777215,0,0,0,0,0,0,10461087,16777215,13619151,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,1447196,1447195,1381402,1052433,1184019,2039072,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1841436,1841437,1841436,1446935,8157007,5196596,854798,3354417,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,0,0,0,0,0,0,0,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,7303023,0,2039583,16777215,16777215,0,0,0,0,0,0,10461087,16777215,13619151,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,6908012,1447195,1447195,1447195,1052433,1841693,1907486,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1841436,1841436,1841436,1841693,1249810,11840879,855054,855054,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,0,0,0,0,0,0,0,16777215,16777215,0,0,16777215,16777215,16777215,16777215,9408399,0,0,0,0,16777215,16777215,16777215,16777215,16777215,16777215,7303023,0,2039583,16777215,16777215,0,0,0,0,0,0,10461087,16777215,13619151,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,15527148,1710367,1447195,1447195,1381402,1709850,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1841436,1841436,1841436,1775643,1841693,1249812,5525303,2236698,855054,15197156,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,0,0,0,0,0,0,0,16777215,16777215,0,0,16777215,16777215,16777215,16777215,9408399,0,0,0,0,16777215,16777215,16777215,16777215,16777215,16777215,7303023,0,2039583,16777215,16777215,0,0,0,0,0,0,10461087,16777215,13619151,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,6645097,1447195,1447195,1512988,1446937,1775644,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1841436,1841436,1841436,1578521,1315346,4210220,855054,10656668,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,0,0,16777215,16777215,16777215,16777215,7303023,0,2039583,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,13619151,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,15461356,1447195,1447195,1447195,1578781,1841437,1841436,1841436,1907486,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1709850,1775643,1775643,1775643,1841436,1841436,1841436,1775643,986384,5262645,855054,7236974,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,0,0,16777215,16777215,16777215,16777215,7303023,0,2039583,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,13619151,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,8224128,1447195,1447195,1578781,1841954,1841693,1841436,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1183763,1315092,1380885,1709850,1775643,1841436,1775643,1775643,920847,8222543,855054,3222830,11119017,10000536,11908533,12171705,13816530,14408667,15263976,15724527,16185078,16514043,16777215,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215,2039583,0,7303023,16777215,16777215,0,0,16777215,16777215,0,0,16777215,16777215,7303023,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,1249816,1447195,1447195,1578781,2367784,1907486,1841693,1841437,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1644057,920590,986383,1052176,1709850,1841436,1841436,1775643,1775643,986383,10656613,855054,1644312,2565927,921102,1052688,1052688,1842204,723723,1118481,986895,592137,1447446,5197647,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215,2039583,0,7303023,16777215,16777215,0,0,16777215,16777215,0,0,16777215,16777215,7303023,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16448509,13360879,13952243,13558000,12572653,10667236,13032430,9681888,12375532,11389927,9747680,9944545,8762076,9418975,9616352,9944801,10470115,11784169,11915497,15463161,16580094,15791611,16120316,16251645,16580094,15922937,8422792,4542555,394502,1315608,1512988,1907747,2104867,1841693,1841436,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1118226,855054,920591,1512471,1775643,1775643,1775643,1775643,1775643,3025697,11314282,855054,1576468,853770,393732,131329,328452,328196,197379,328452,328452,328451,591111,4604741,16777215,16777215,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,16777215,16777215,14013909,13619151,15000804,16777215,16777215,0,0,16777215,16777215,13619151,13619151,16777215,16777215,15000804,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,13619151,16777215,16777215],[16777215,16777215,16777215,16711423,16711679,16711679,16711422,15134711,13689586,7054036,7842264,8433627,8630747,8959197,7250901,5871568,5608654,5937104,5411533,5214668,7973592,7054036,11849961,14806261,16120316,15660282,14806263,15922939,16382716,15725301,11316913,2501165,659735,921877,262916,1249815,1512988,2630958,1907487,1841693,1841436,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1709850,920847,920590,1052176,1512728,1578264,1644058,1644057,1709850,1644057,4143915,6446143,2954274,2428955,919050,525061,656391,853513,722183,853513,1050635,328196,328196,525317,4670277,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16711423,16711679,16777215,16645887,13689329,11127270,6528466,5739983,5739983,6133968,5345997,5345741,5937103,6397138,6331345,7251157,8696540,14280692,15791867,15857659,15988731,15857659,15463160,15593974,15856370,15592941,13092807,6447714,1249811,65793,131330,328965,1315608,1578781,2828337,1841693,1841436,1841436,1841436,1841436,1775643,1775643,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1709850,920591,1510932,3151140,3085603,2954274,3085603,2888737,2888737,3020067,3610920,5651001,6637890,10785127,11838063,11442796,11047017,10388579,10059616,9796190,9533020,8809557,8217936,7560520,9075566,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,10790052,9408399,12171705,16777215,16777215,9408399,9408399,9408399,9408399,9408399,9408399,15856113,16777215,13553358,9408399,9408399,0,0,9408399,9408399,9408399,9408399,9408399,9408399,13553358,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,9408399,9408399,9408399,9408399,10790052,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,8827869,8236506,9353439,7973849,7645399,6659795,5345741,5214413,5214412,6002896,5214412,4951755,5411533,11849961,12441067,14806262,15463160,15857659,15857403,16382973,15922680,15724528,15066854,14935011,12105912,3552822,394758,1,65793,197123,657675,789260,1381401,1644574,2302245,1841436,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1578264,855054,2757408,6562615,6759225,6562616,6431287,6365750,6234678,6168886,6169142,6103605,5775924,9266517,14864777,15193739,15721105,15260045,14996618,15062411,16313494,15918483,15655313,16379287,15721898,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,3092271,0,6250335,16777215,16777215,0,0,0,0,0,0,14671839,16777215,9408399,0,0,0,0,0,0,0,0,0,0,9408399,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,0,0,3092271,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,6134225,5543119,5674447,4951756,6068688,5148877,4951755,4885963,4754635,4885963,7776728,14346484,15266040,16120060,15594490,15988731,15463161,15528696,15790578,15329769,15198183,12105656,3223601,65794,65537,0,65793,394502,920591,920847,986383,920847,1381401,2367786,1973280,1775643,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1315092,855054,3872809,7218747,7218747,7218747,7218747,7218747,7218747,14533764,15851922,15917714,15983763,16181397,16510872,16708506,16774299,16378774,16246932,16180883,15916943,15785101,15455626,13742972,13150351,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,3092271,0,6250335,16777215,16777215,0,0,0,0,0,0,14671839,16777215,9408399,0,0,0,0,0,0,0,0,0,0,9408399,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,0,0,3092271,16777215,16777215,16777215,16777215],[16711422,16711422,16514301,5214669,4951755,5083084,6200017,5937104,4820171,5345741,7908056,13426672,13360879,15003383,15463161,15397368,16054267,16251644,16054007,15921906,15395562,13684944,7697781,197379,0,263170,1184267,4604715,10327649,3683623,920591,986383,986383,1052176,986383,1381657,2696751,1841694,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1709850,1052176,920591,5119281,7218747,7218747,7218747,7218747,7218747,7482173,13017973,15852178,16247189,15851921,16313238,16313237,15916942,13805679,10375230,10375230,10375230,10309438,9520189,7284539,7218747,9591916,16777215,16777215,16777215,16777215,16777215,16777215,0,0,13619151,16777215,16777215,16777215,16777215,0,0,16777215,16777215,0,0,0,0,7303023,16777215,16777215,0,0,0,0,0,0,0,0,9408399,16777215,16777215,16777215,16777215,0,0,0,0,0,0,10461087,16777215,13619151,0,0,16777215,16777215],[15660282,16645886,15726074,5477326,5017292,5148877,5017548,7054037,12835310,15988732,15922939,15660282,15857403,15857403,15791610,15791093,15856114,16119285,13882323,7829367,1973790,0,65793,789512,4276008,10920037,15853459,14932619,13617023,7959630,2104603,1578264,1775643,1775643,1117970,1512988,2828338,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1644057,920591,1445395,6825017,7218747,7218747,7218747,7218747,7218747,7219003,11831657,14006655,13347447,12622448,12885359,13938034,13278312,12090454,10375230,10375230,10375230,8928316,7350331,7218747,7218747,9001321,16777215,16777215,16777215,16777215,16777215,16777215,0,0,13619151,16777215,16777215,16777215,16777215,0,0,16777215,16777215,0,0,0,0,7303023,16777215,16777215,0,0,0,0,0,0,0,0,9408399,16777215,16777215,16777215,16777215,0,0,0,0,0,0,10461087,16777215,13619151,0,0,16777215,16777215],[14017779,15726074,11587048,5411534,5083084,5017548,5739983,14346484,16054524,15857402,15857403,15331832,15331059,16054006,15987699,15724527,9408399,1579033,65794,65793,1184267,2104851,9538649,14603655,15524496,16182421,16050836,15129740,13419391,8156753,4670003,2236191,1775643,1775643,986383,1644575,2894131,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1512471,855054,2363932,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284283,7415867,7350075,8599356,10375230,10375230,10375230,10375230,10375230,8270908,7350331,7218747,7218747,6759481,6836317,16777215,16777215,16777215,16777215,0,0,0,0,13619151,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,2039583,0,7303023,16777215,16777215,16777215,16777215,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10461087,16777215,16777215,16777215,16777215,16777215,16777215],[9944545,8893405,8959197,4820427,5411533,4820171,6791123,12966638,15660282,15857145,14935784,14211546,14211289,10658210,1513239,65793,0,197378,2368022,7367748,15853714,15524752,16116885,16116629,15327118,14669705,15919251,13814402,8485716,4275504,1775643,1775643,1775643,1775643,1052177,1907491,2894131,1841436,1775644,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1117970,855054,3938345,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7415867,7284539,10177854,10375230,10375230,10375230,10177853,8139579,7415867,7218747,7218747,6825017,3610407,6704987,16777215,16777215,16777215,16777215,0,0,0,0,13619151,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,2039583,0,7303023,16777215,16777215,16777215,16777215,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10461087,16777215,16777215,16777215,16777215,16777215,16777215],[7119573,7251158,8433627,4820171,4885963,4754635,13032431,15726074,16580094,16448507,8027002,3355443,65793,65793,65793,723463,6051896,12103792,15129996,15985300,16182422,15327374,16248214,16445592,15458959,13353853,7893839,2301984,1775643,1775643,1775643,1775643,1775643,1775643,1117970,2105126,2828338,1841693,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,855054,855054,5775411,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284283,8468027,7679035,10375230,10375230,10375230,10112062,8007739,7613243,7218747,7218747,6890553,3807017,3413541,8870248,16777215,16777215,0,0,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,9408399,16777215,16777215,16777215,16777215,0,0,16777215,16777215,0,0,10461087,16777215,16777215,16777215,16777215,16777215,16777215],[5674446,5345997,6725587,4820171,4820171,5543118,15594490,16185852,16185591,13355979,263172,65794,65793,723464,11380330,15393166,16116629,15853715,15261582,15524496,15722130,15919507,15919252,8880215,2170650,1512470,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1184020,2236456,2565421,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,920847,1248786,6759480,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7744827,8994108,10375230,10375230,9783357,8270908,7481659,7284539,7218747,7087418,3807017,3544615,6628152,9591916,16777215,16777215,0,0,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,9408399,16777215,16777215,16777215,16777215,0,0,16777215,16777215,0,0,10461087,16777215,16777215,16777215,16777215,16777215,16777215],[10010337,6791123,5083084,4820171,4754635,11455720,15660282,15594489,15790061,6908010,394503,2499610,15327117,16116629,15985044,15458703,15590544,13814145,16116628,15327375,11709296,3749164,1775643,1709850,920590,1512727,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1578264,1315608,2367786,2499371,1907486,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1578264,855054,1904664,7152954,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7679035,10112317,10309437,9651773,8007739,7613243,7218747,7218747,7218747,4200748,3413542,5578547,7218747,9591916,16777215,16777215,16777215,16777215,16777215,16777215,0,0,0,0,6250335,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215,16777215,16777215,0,0,0,0,9408399,16777215,14671839,0,0,16777215,16777215,16777215,16777215,0,0,0,0,3092271,16777215,16777215,16777215,16777215],[5674447,5017292,4885963,4754635,4885963,15069176,15266296,15200503,14803168,920591,4341293,15853715,14735240,15064204,14208901,14603656,13879938,10985577,5393722,1775643,1775643,1775643,1775643,1709850,920591,1578264,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1446678,1447195,2565422,2236196,2039073,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1183763,920590,3544868,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,8073531,10177854,8599612,7416123,7350075,7350075,7218747,7218747,4856623,3479078,5119280,7218747,7218747,9591916,16777215,16777215,16777215,16777215,16777215,16777215,0,0,0,0,6250335,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215,16777215,16777215,0,0,0,0,9408399,16777215,14671839,0,0,16777215,16777215,16777215,16777215,0,0,0,0,3092271,16777215,16777215,16777215,16777215],[5017292,4820171,4951756,4754635,8565211,14674934,15397881,15660021,11645362,854798,7367496,15590545,15064204,15327375,11314284,5065015,1973021,1775643,1775643,1775643,1775643,1775643,1775643,1709850,855054,1644313,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1315349,1578781,2630959,2302246,2039073,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,986640,920591,5119279,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,8533820,7547451,7415867,7218747,7218747,7218747,7218747,7218747,7021882,4856880,7218747,7218747,7218747,9591916,16777215,16777215,16777215,16777215,16777215,16777215,12566463,12566463,12566463,12566463,14145495,16777215,16777215,12566463,12566463,12566463,12566463,12566463,12566463,12566463,12566463,12566463,12566463,12566463,16777215,16777215,4144959,4144959,0,0,0,0,9408399,16777215,14671839,0,0,16777215,16777215,4144959,4144959,12566463,12566463,12566463,12566463,10987431,4144959,4144959,16777215,16777215],[4754635,4754635,4951756,4754635,12243948,15069176,15528953,16054002,2960430,854798,10064480,11117161,7498571,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1709850,920591,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1249556,1381400,2762545,2499627,2302246,1907486,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1709850,920847,1051920,6365751,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7481659,7284283,7218747,7218747,7218747,7284283,7218746,7087418,7021882,7021882,7152954,7218491,7218747,9591916,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,0,0,0,0,9408399,16777215,14671839,0,0,16777215,16777215,0,0,16777215,16777215,16777215,16777215,13619151,0,0,16777215,16777215],[5148876,4885963,5083084,4754635,14346484,15463161,15068919,14409435,1184019,855054,2039064,1249299,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1709850,986640,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1381142,1578781,2828337,2039073,1841693,1841693,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1578520,920591,1511187,7152955,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,8007995,7284283,7218747,7284539,6496823,4856879,4069676,4201517,4990258,5712693,4858417,4463405,5578546,9460587,16777215,16777215,10461087,10461087,10461087,10461087,10461087,10461087,10461087,10461087,10461087,10461087,10461087,10461087,10461087,10461087,10461087,16777215,16777215,11250603,10461087,10461087,10461087,10461087,10461087,10461087,6250335,6250335,6250335,6250335,0,0,9408399,16777215,15461355,6250335,6250335,16777215,16777215,6250335,6250335,10461087,10461087,14408667,16777215,14803425,6250335,6250335,16777215,16777215],[5214412,4820171,4820171,5345741,15594745,15923195,15594489,14474459,854798,855054,855054,1512471,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1644057,1052433,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1512730,1644574,2828338,2170659,1907486,1841693,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1380885,986383,2298138,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7350075,7350075,7218747,5250610,5252402,6041144,6829629,9459530,10181962,9918022,7749183,7026494,5449781,6836317,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215,2039583,0,0,0,0,0,0,16777215,16777215,16777215,16777215,0,0,9408399,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,10461087,16777215,16777215,16777215,16777215,16777215,16777215],[5083084,4820171,4951755,7185365,16120316,15594746,15791352,10395038,854798,920591,855054,1644057,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1512471,1117970,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1446936,1578780,2959924,2038817,1973279,1973279,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1118226,920847,4135209,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7415867,7415867,4726320,3807273,7749184,12743760,13271641,13139542,13205848,12546125,12480076,12479820,11428425,9792623,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215,2039583,0,0,0,0,0,0,16777215,16777215,16777215,16777215,0,0,9408399,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,10461087,16777215,16777215,16777215,16777215,16777215,16777215],[4885963,4754635,4820171,8827869,16120060,15791611,15527923,6184030,854798,986383,920591,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1315092,1183762,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1381399,1447194,2894131,2301990,1907486,1907230,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,920847,920590,6103093,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,8007739,6170164,4004396,7684157,12875859,14919540,13205592,12677967,12480076,12479820,12479820,12479820,12479820,13537656,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,2039583,0,0,0,0,16777215,16777215,16777215,16777215,0,0,16777215,16777215,7303023,0,0,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[4885963,4754635,4754635,10995942,15791611,15988988,15067112,3881276,854798,920590,1117969,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1183762,1249299,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1841437,1315606,1512987,2894131,2367784,1907486,1841693,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1644057,920591,920590,7152954,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7679291,3938602,4924209,13403741,16171917,15974023,13469019,12546125,12480076,12479820,12479820,12479820,12479820,13537656,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,2039583,0,0,0,0,16777215,16777215,16777215,16777215,0,0,16777215,16777215,7303023,0,0,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[4754635,4754635,4754635,13360880,16448509,16054523,12500671,2104865,854798,920591,1380885,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,986640,1249556,1775643,1775643,1775643,1775643,1775643,1775643,1775643,2039073,1447193,1644574,2959924,2565164,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1578264,855054,1314579,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,5381681,3479078,11169622,16568217,15446912,12743760,12545869,9391427,7157821,6763580,6829373,7814463,11822409,13537656,16777215,16777215,0,0,16777215,16777215,0,0,0,0,0,0,0,16777215,16777215,0,0,16777215,16777215,16777215,16777215,9408399,0,0,0,0,16777215,16777215,0,0,0,0,0,0,2039583,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215],[4754635,4754635,4885963,15725818,16383229,15923195,13092808,854798,855054,920847,1578264,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,920847,1446678,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1907486,1447193,1512988,2959924,2697007,2104866,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1381141,920590,2560798,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284283,7218747,7218747,7284283,4397868,4661295,16700059,16700059,15315326,12941907,8602945,6829373,6304059,6304059,6304059,6304059,6566459,9464174,16777215,16777215,0,0,16777215,16777215,0,0,0,0,0,0,0,16777215,16777215,0,0,16777215,16777215,16777215,16777215,9408399,0,0,0,0,16777215,16777215,0,0,0,0,0,0,2039583,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215],[4754635,4754635,5805775,15923195,16120060,15988988,10658210,854798,855054,920847,1709850,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,855054,1512471,1775643,1775643,1775643,1775643,1841436,1841436,1841436,2039072,1710109,1512988,2959924,2894131,1841436,1775900,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1117969,920590,4397612,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284539,7284283,7218747,7218747,7284283,4922930,8147785,16700059,16700059,15512961,7617855,6632508,6369596,6304059,6304059,6304059,6304059,6304059,9267053,16777215,16777215,0,0,16777215,16777215,0,0,0,0,0,0,0,16777215,16777215,0,0,16777215,16777215,2039583,0,7303023,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215,6250335,0,3092271,16777215,16777215,16777215,16777215],[4754635,5280205,7119573,15397625,16054267,14738921,7105389,854798,855054,986384,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,920590,1578520,1775643,1775643,1775643,1775643,1841436,1841436,1841436,1841437,1381398,1512988,2959924,2894131,1841436,1775644,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1709850,855054,920847,5906485,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284539,7284539,7218747,7218747,7284283,4069932,9069649,16700059,16700059,15515790,6500924,6304059,6369596,6304059,6960702,7486270,10245701,11954250,13472120,16777215,16777215,0,0,16777215,16777215,0,0,0,0,0,0,0,16777215,16777215,0,0,16777215,16777215,2039583,0,7303023,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215,6250335,0,3092271,16777215,16777215,16777215,16777215],[4951499,5017292,10404579,15331832,15594489,15922164,5197391,854798,920847,1052176,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,986383,1644057,1775643,1775643,1775643,1775643,1775643,1841436,1841436,1841693,1315606,1644574,2828338,2959924,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1709850,855054,1314579,7021882,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284283,4529199,9069649,16700059,16700059,14660741,7552063,6500924,6369596,6960701,12216651,12479820,12479820,12479820,13537656,16777215,16777215,0,0,16777215,16777215,0,0,0,0,0,0,0,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,0,0,0,0,2039583,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[4951500,4820171,13098223,15266040,15594746,14539997,1841693,920590,986383,1315348,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,920591,1775643,1775643,1841436,1841436,1841436,1841693,1907230,1907486,2039072,1512729,1644574,2762801,2894131,1841436,1841693,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1644057,986383,2035994,7087418,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7350075,7284539,7218747,7284539,4332333,9464405,16700059,16700059,14792070,9924696,6632509,6960957,12216907,12479820,12479820,12479820,12479820,13537656,16777215,16777215,0,0,16777215,16777215,0,0,0,0,0,0,0,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,0,0,0,0,2039583,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[4820427,4820427,16185852,15857402,15069175,15000804,855054,920590,986383,1644057,1775643,1775643,1775643,1775643,1841436,1775643,1841436,1841436,1775644,1775643,1907230,1973279,2039073,1118226,2236196,2236453,2302246,2302246,2368039,2368039,2368039,2368039,2368039,1710365,1512988,2762545,2959924,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1512471,920591,2757408,7152954,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7350075,7218747,7284539,7218747,4397612,9200465,16700059,16700059,16042131,9596246,7159361,10114373,12480076,12479820,12479820,10442566,7354942,9463917,16777215,16777215,0,0,16777215,16777215,12566463,12566463,12566463,12566463,12566463,12566463,12566463,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,4144959,4144959,4144959,4144959,12566463,12566463,12566463,12566463,11513775,4144959,4144959,4144959,4144959,12566463,12566463,4144959,4144959,12040119,16777215,16777215,16777215,16777215,16777215,16777215],[5083084,4820171,16251645,16054524,14937589,10592673,855054,920847,1052433,1907486,1907486,1841436,1973279,2039072,2170659,2302246,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1249556,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1776157,1512988,2762545,2894131,1841436,1907229,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1315092,855054,4134953,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,5250353,7488578,15844754,16700059,16700059,9464661,9398612,11625801,12480076,12479820,9260099,6566717,6369596,8938604,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,16777215,16777215,16777215,16777215,16777215,16777215,16777215,0,0,0,0,0,0,16777215,16777215,16777215,16777215,14671839,0,0,0,0,16777215,16777215,0,0,10461087,16777215,16777215,16777215,16777215,16777215,16777215],[4951755,6594003,16054524,15397625,15002352,7960698,1118226,1315349,1184020,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1184020,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1841694,1381144,2630959,2894131,1907486,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,920591,986127,5447218,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,6759481,5121331,12424560,16700059,16700059,15252875,9333332,10449238,12414540,11757130,6501180,6369596,6632253,9069932,16777215,16777215,0,0,11513775,11513775,11513775,11513775,11513775,11513775,11513775,11513775,11513775,11513775,11513775,0,0,16777215,16777215,16777215,16777215,14474460,11513775,11513775,0,0,5197647,5197647,5197647,5197647,16777215,16777215,13816530,11513775,10066329,0,0,5197647,5197647,16777215,16777215,0,0,10461087,16777215,15790320,11513775,11513775,16777215,16777215],[5017291,9681888,15988988,15988731,14935786,4868684,1118226,1249556,1249557,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2302246,1315349,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1973280,1315350,2565166,2894132,2104867,1841693,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,986640,1379859,6234678,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,4332590,9727832,16436888,16700059,16700059,12621938,9530197,9263434,7749183,6369596,6369596,6566460,9267053,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215,16777215,16777215,9408399,0,0,0,0,16777215,16777215,16777215,16777215,16777215,16777215,7303023,0,0,0,0,16777215,16777215,16777215,16777215,0,0,10461087,16777215,13619151,0,0,16777215,16777215],[4820427,12572653,15791611,16448766,15132905,1381399,1118227,1183763,1710108,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2170660,1249813,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2039074,1249812,2433836,2959924,2301990,1907486,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,920847,1839128,6628152,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284283,7218747,7218747,7350075,7746618,8674381,12687476,16700059,16700059,16634266,12227182,9333076,8279883,6369852,6566716,6500924,11238002,16777215,16777215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16777215,16777215,16777215,16777215,9408399,0,0,0,0,16777215,16777215,16777215,16777215,16777215,16777215,7303023,0,0,0,0,16777215,16777215,16777215,16777215,0,0,10461087,16777215,13619151,0,0,16777215,16777215],[4754635,13295343,15857659,16120060,16119543,1118227,1118227,1249556,2039073,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2170659,1249556,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2236453,1249556,2302249,2959924,2499370,2039072,1907229,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1578264,986383,2888736,7152954,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284283,8928572,6764605,8938321,10714464,16700059,16700059,16700059,15318668,11371878,9726294,7026750,6566716,13406328,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[5083084,13426416,15068919,15594746,14737633,1118227,1118227,1249813,2170660,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2104866,1315349,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2302246,1315349,2104869,2959924,2828337,1841693,1841693,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1315348,920591,3872553,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7613499,9126204,8543052,8938577,11964268,16700059,16700059,16700059,16700059,16700059,15711369,12217163,13538169,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[5017291,14543349,16054524,15463161,13684944,1118227,1183763,1249556,2236453,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2039073,1381142,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1315350,2236198,3946307,4209479,1841436,1841693,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1052433,1117456,4725550,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7547451,7679035,9191485,8471614,8608845,10319709,16700059,16700059,16700059,16700059,16700059,16700059,16567959,13402970,12480332,12480076,12480076,12479820,12546125,10837577,3873578,5121588,8206396,7876155,7678779,7547451,7415867,7744571,7218747,6956089,5053744,3741737,3545128,5447731,3348005,3151140,1248529,328965,131330,131330,65793,65794,131586,1248529,3479335,4528942,5644083,3020067,920590,1644057,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,986383,986384,1775643,1841436,2170660,2894131],[5017292,15068919,16054524,15791096,13684688,1118227,1183763,1249813,2236453,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1973281,1249813,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1381143,2302249,4275272,4406601,1841436,1841693,1775643,1775643,1775643,1775643,1775643,1775643,1775643,986383,1445395,4856879,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7481659,7679291,8534076,10375230,6763321,6700095,9793368,15384462,16634266,16700059,16700059,16700059,16700059,16699802,15182714,13007445,12480333,11298123,7223869,4135468,4398637,9193020,10375230,9191741,7679035,7416123,7350075,7284539,7481659,7415867,7218747,6825017,3938345,3675945,3282213,2166297,328195,65793,0,131330,197379,1051151,3348262,4791343,7087419,7218747,5972276,3348006,920590,1183762,1775643,1775643,1841436,1841436,1775643,1775643,1841436,1841436,1644057,920847,1315349,1841436,1512729,1710368],[4820171,15857403,15660282,15462902,13750737,1118227,1183763,1249813,2302246,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1973281,1315349,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1315607,2170662,4340808,4341064,2104865,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1775643,920847,2429469,5578547,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284283,7350075,8205116,10375230,10375230,7748410,6698813,9266770,11108964,13542780,15450254,15779217,15647632,14858377,13805950,12490097,8080967,5976121,5187124,6697526,9915197,10375230,10375230,10375230,9914941,7810619,7350075,7415867,7613243,7284283,7547451,7547451,7218747,4987952,3216676,2822688,656391,196866,262916,1116943,3085859,5119024,6890554,7218747,7218747,7218747,5906484,3348006,920590,986384,1249556,1907486,1841436,1841436,1841436,1841436,1841436,1841436,1775900,920847,1052433,1709850,1775900,1315608],[5017292,15594745,15660282,15791094,11776947,1118227,1183763,1315349,2302246,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1973280,1315349,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2433834,2696751,1710367,2105126,4275015,4340808,2762284,1841693,1841436,1775643,1775643,1775643,1775643,1775643,1775643,920847,3544615,6365751,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7350075,7284539,8007996,10375230,10375230,10375230,9784125,7682875,6371133,7687237,8542540,8411211,8542283,7819080,6634559,5713465,5909816,8536380,9915453,10309438,10375230,10375230,10375230,10375230,10375230,10309438,9060157,7350075,7416123,7350075,7350075,7284539,7284283,7218747,5053488,3282212,1575441,2034967,3347748,5840949,7021882,7218747,7218747,7218747,7218747,7218747,6037813,3479335,920847,1249555,986640,1052433,1446935,1709850,1446678,1381142,1249556,1052177,986384,1052433,986640,1052433,1907486,1183764],[5214413,15463417,16120316,15791351,12171706,1118227,1249556,1249813,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2433832,2499627,2631213,2762545,2368299,1644574,2959924,2959924,2959924,2959924,2894131,2828338,2894131,2894130,2959924,2959924,2039077,1973284,4143685,4341065,3288373,1841436,1775900,1775643,1775643,1775643,1775643,1775643,1709850,920847,3610408,7021626,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284539,7284283,7284539,8007995,10309438,10375230,10375230,10375230,10375230,10375230,9849662,8930878,8865598,8273724,8996157,9981246,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10178109,7876155,7613243,7350075,7284539,7284283,7415867,7087418,3610152,3610151,6168886,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,6694456,4004396,986640,1710107,1578521,986384,920847,920590,920590,920590,920847,986384,1183762,1841693,1446935,1052433,1184019,1052433],[5214413,15923195,15397369,14936301,13027014,1118227,1315349,1315606,2368039,2368039,2368040,2433833,2499626,2630957,2762543,2828337,2959923,2959924,2959924,2959924,2959924,2959924,2433836,1644574,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2433836,1710368,4012099,4406601,3683132,1907486,1841436,1775643,1775643,1775643,1775643,1775643,1578520,1051920,3544615,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284539,7218747,7218747,7547451,10177854,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9980733,8994364,8468028,7415867,7547451,7481659,7547451,7284283,7284794,7218747,7218747,7218747,7218747,7218747,7218747,7284539,7218747,7218747,7350075,6825784,3610408,986640,1710107,1841693,1841437,1446935,1249812,986384,1315605,1775900,1841693,1907486,1907486,1973279,1315605,1184020,1184020],[5280205,15068920,15660282,15791093,12829637,1447194,1578781,1710368,2894131,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2433835,1710111,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2631215,1512989,4012099,4472394,3946305,2170658,1841693,1775643,1841436,1775643,1775643,1775643,1512727,2101529,3610150,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284539,7218747,7218747,7613243,10112062,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10309438,10309438,9651773,9060156,8994108,8994108,8731196,7876411,7744571,7547451,7415867,7350075,7350075,7350075,7350331,7350075,7415867,7284283,7415867,7481659,7613244,7481659,6562871,3544871,920591,1775643,2039072,1841693,1841693,1841437,1841436,2368039,2039329,2039073,2104865,2170660,2302247,2302247,1512986,1841696],[5608655,15266040,15069176,15396852,12369085,1447195,1644575,1776160,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2433835,1644574,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2762545,1578781,3354425,4472394,4143685,2104608,1841436,1775643,1775643,1775643,1775643,1775643,1380885,3085347,3872809,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7350075,7218747,7218747,7481659,9980734,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10046269,9323069,9125693,9191484,8994108,8994108,8862780,8862780,8270908,7679035,7481659,7679035,8402236,7744828,7416123,7613243,7481659,7481659,8796988,9454397,7744828,7350075,6431287,3544615,920847,1709850,1841693,1841436,1841436,1841693,1841693,2433832,2368039,2302246,2368040,2368039,2368039,2368039,2368039,2630957],[5542862,16054523,15660282,15396336,11513777,1447195,1644575,1841698,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2433836,1644574,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2894131,1578781,2433836,4472394,4340808,2499111,1841693,1841436,1775643,1775643,1775643,1775643,1249556,3085603,4069418,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284283,7218747,7218747,7284283,7284539,7284539,8007739,10177854,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10112061,9125948,9125692,8994108,8994364,9191484,9060156,9191484,8994364,8862524,8994364,8928572,8007739,8204859,8336700,8007996,7679035,8139323,8928572,9783613,10309438,9651773,7547451,7679035,6497079,3479079,986640,1709850,1907486,1907229,1841437,1841436,1841436,2368039,2368039,2368039,2433833,2630957,2828337,2959924,2959924,2959924],[5937103,15594746,15988731,15856886,11053226,1447195,1644574,1841697,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2499629,1644318,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2894132,1710368,1907747,4406601,4340808,3288629,2170659,1841437,1775643,1775643,1775643,1775643,1183763,3020323,4791086,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284539,7350075,7416123,7547707,10046525,10441023,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10309438,9717565,9257277,9059900,8862780,9059900,8928572,8928572,8928572,8994108,8994108,9059900,8862524,8928316,8862524,8862524,8468284,8796732,8994364,9454652,10243645,10375230,10309438,9520445,7415867,7613243,6825784,3282469,986640,1907230,1973279,1907486,1841436,1841693,1841436,2565420,2762544,2894131,2959924,2959924,2959924,2959924,2959924,2959924],[6725587,15068919,15266296,15528180,10197661,1447195,1578781,1775904,2959924,2959924,2959924,2959924,2959924,2959924,3091510,3354426,3617342,4077636,4209478,4077893,4209222,4275015,3683134,2039591,4209222,4340808,3946307,3157304,3157047,3157303,3222840,3157303,3157047,3091510,3091510,1973284,1776161,4340808,4340808,3288628,2039072,1841436,1775643,1775643,1775643,1775643,1183506,3020323,5578291,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284283,7415867,7942204,10243646,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10243646,9454652,8994108,9651773,8928572,8928572,8928316,8994108,8862780,8862780,8862780,8928572,8862780,8862524,8862780,8928572,8862780,9257276,9454397,10112061,10309438,10375230,10375230,10375230,9585981,7613243,7547707,6694199,3348006,920590,1315349,1841436,1841437,1841693,1841693,1841436,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924],[6988244,15922939,15791610,15462645,10000283,1447195,1644575,1841698,3025718,3485756,3880514,4143685,3946307,4209479,4209222,4340809,4406601,4340809,4275015,4867151,5722202,5853788,4998737,3223096,5985118,5853788,5787739,5590617,5919581,5787996,5393238,5853532,5853788,5787995,5722203,4077891,2631215,5459031,4998737,3485495,1907229,1841436,1841436,1775643,1775643,1775643,1117713,3020067,6431287,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284539,7415867,7350075,7679035,10243902,10375230,10309438,9980989,10243902,10309438,10375230,10375230,10243646,10375230,10375230,10375230,10309438,10309438,10309438,9454652,9191484,9454396,8994108,9191740,9060156,8928316,8862780,8862780,8862780,8862524,8862524,9060156,8994364,8928316,8928316,8928572,9060156,9651773,10375230,10375230,10375230,10375230,10375230,10375230,9585981,7415867,7415867,6628664,3676201,920591,920847,1052433,1578521,1775644,1907486,1841436,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924],[7119829,16251388,16251644,15199730,9473938,1447195,1578781,1907747,3091511,3880514,4012100,3946307,4143429,4209222,4406601,4340808,4275015,4341064,4406601,4406858,5722202,5853532,5196116,3288633,5919325,5919325,5787996,5722202,5919581,5853788,5853788,5919325,5919325,5853788,5919325,5064273,3157304,4998994,4932945,3683389,2038815,1841436,1775643,1775643,1775643,1775643,1052177,3151396,7152955,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284539,7218747,8533820,10243646,10375230,6763321,5187125,8405052,10243646,9980733,9454653,9783357,8468284,8336443,7876155,9323068,9848893,9191484,9322812,9191740,9257276,8862780,8863036,8994364,8928316,8796988,8862524,8862780,8796988,8928572,8862524,8862780,8862780,8928572,9191740,10178109,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9651773,7876411,7416123,6628663,4660529,1118226,1446935,1052433,986383,986640,1644571,2104866,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924],[7251157,15726074,15660282,15462386,9013387,1447195,1578781,1841954,3222840,3683135,4077636,4143686,4012100,4275015,4340808,4472394,4340808,4406601,4340808,4406601,5459031,5787995,5130066,3222841,5787995,5919325,5853788,5853789,5853789,5853788,5656410,5853788,5919581,5853788,5787995,5459031,3157048,4275527,4932944,4077892,2367524,1907229,1841436,1775643,1775643,1709850,986641,3020067,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7284283,7218747,6759993,7744827,9520445,8602172,5646647,4464944,6893878,7416123,7547451,8336700,7744571,7350075,7547451,7941948,8139323,9125692,8994364,9125948,9191485,9125692,8862524,8862524,9059900,8928572,8862524,8862524,8862780,8862780,8796988,8928316,8862780,8862780,9914685,10309438,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10309438,9520445,7678780,7284539,6628663,3348006,986640,1710107,1775900,1644314,1052433,920847,1052690,2565421,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2368042],[7776728,15660538,15200504,15593716,8026749,1447195,1578781,1578781,3288890,3946307,3814978,4340808,4340808,4341064,4275015,4275271,4275015,4406601,4275271,4143686,5327445,5919325,5196115,3091510,5853532,5853789,5722203,5853532,5985118,5919325,5985118,5985118,5985118,5985118,5919581,5919325,2959925,3551805,4998737,4472651,2499110,1841436,1841436,1775643,1775643,1644057,1118228,3216933,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,5906485,3282469,4922928,7219002,4267310,4004396,4529968,6170421,7679035,7941947,7941947,7679035,7679035,7941947,7547451,7810363,8599868,9322812,8928316,9125692,8928316,8862780,8862524,8862524,8862780,8862524,8796988,8796988,8862780,8862780,8862780,9257276,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10309438,9585981,7416123,7547451,6562615,3413542,920590,986383,1578521,1775900,1841693,1512728,1118227,1512988,1578782,2697008,2894131,2959924,2959924,2959924,2894131,1512987],[7579607,13492465,15594746,15725559,8618629,1447195,1578781,1578782,3486013,3749184,4275015,4341065,4143686,4406601,4472394,4472394,4340808,4406601,4406602,4406857,5327446,5919325,5327445,3288890,5919582,5853788,5919325,5919582,5919581,5919581,5919325,5853789,5985118,5985118,5853789,5853788,3025718,2959924,5327445,4538186,2695977,1841693,1841436,1775643,1775643,1709850,1315608,3413798,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7350075,3938345,3216676,4594478,4857136,3873066,8405568,4332847,5776692,8205116,7876155,7876155,7613243,7810620,7481659,7481659,7481915,8533820,8731196,8994108,8928572,8862524,8862780,8862524,8862524,8862524,8862780,8862524,8862524,8862780,9059900,10046269,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10309438,9585981,7744827,7284283,6628408,3676201,1118226,986640,986383,1052176,1644314,1841436,2039072,2170920,1710368,1644574,1973284,2762801,2959924,2959924,2959924,2039077],[8039385,15726074,15397625,15791351,7631992,1447195,1578782,1578782,3551805,3946307,4209222,4406601,4341064,4406602,4406601,4406601,4472394,4472394,4406602,4472395,5393238,5656410,5525080,3223097,5985118,5919582,5919581,5919581,5919581,5787996,5787995,5919325,5853532,5985118,5985118,5853788,3354426,2762802,4932944,4472650,2959405,1841693,1841437,1841436,1841436,1709850,1249816,3413799,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,6300214,3413542,4070187,3741737,3479078,5317424,13205848,4004908,5382706,8139324,7547451,7613243,7679035,8007995,8270907,7876411,7942204,8402492,8665404,8994108,8862780,8928572,8862524,8862524,8862780,8862780,8862780,8862780,8796988,9586237,10309438,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9585981,7612987,7547195,6628663,3545128,1249556,1973279,1447191,986640,986384,1118226,1775900,2959924,2828338,2104870,1512988,1841953,2959924,2959924,2959924,2104870],[8959197,15200248,14937591,14477555,6842219,1447195,1512988,1644574,3222841,4143429,4275272,4340808,4406601,4472394,4341065,4406601,4406602,4406601,4340808,4406601,5459031,5722203,5722203,3222840,5985118,5919581,5787739,5985118,5853788,5919581,5853788,5787995,5787995,5919325,5919581,5919581,4209222,2499629,4801359,4406857,2893869,2104865,1841436,1841693,1841436,1644057,1249817,3413798,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7152954,4200747,3413541,6631995,3348005,4135468,12085835,12678223,3939114,3610920,3676201,3610664,3544871,3610921,3610407,4332590,4135724,3873322,4004908,4398895,7878202,9454652,8862780,8862524,8928316,8862780,8862780,8862780,9125949,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9586237,7481659,7481659,6825784,4135468,1052177,1709851,1841437,1973280,1381398,986640,986384,2433835,2959924,2959924,1841698,1776161,2959924,2959924,2959924,2170664],[7776727,15266040,15594746,15922937,7895163,1447195,1512988,1578782,3288633,3946306,4340808,4406601,4406602,4406601,4406601,4406601,4406601,4341065,4340808,4472394,5130067,5722202,5787996,2959924,5853788,5787739,5787995,5919581,5853788,5853788,5853789,5919581,5787996,5787996,5919325,5787995,4341064,2762545,4406857,4341064,3288629,2104609,1841436,1973279,1841436,1644314,1315609,3807274,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,7218747,6890553,6431543,5840948,5119025,4856879,3610151,4922415,6697789,4596015,9917764,12545869,12611919,10182476,9393993,8669762,8933959,8472642,8866628,9590344,8735299,8998981,9459272,9987409,4398895,7352888,9322812,9191228,8994364,9059900,8928572,8994108,9914941,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10309694,9585981,7810620,7481659,6628664,3544615,986384,1709850,1841436,1841436,1841436,1644314,986383,1710367,2959924,2894131,1644574,1841698,2959924,2959924,2959924,2302506],[6594002,14937591,15397625,15528953,11119019,1447195,1512988,1578781,2959924,3748928,4209479,4275271,4406602,4406601,4340808,4340808,4341064,4340808,4406601,4275272,5327702,5853532,5787739,3223097,5919325,5919582,5919325,5787995,5787996,5656666,5722202,5853532,5919325,5919325,5261652,5261652,4867151,2236456,3683391,4406601,3814975,2433574,1907486,1973279,1841436,1710107,1381402,3216676,6300215,7218747,7218747,7218747,7218747,7218747,7218747,7087418,5381682,4003882,3610408,3610408,3413286,3807529,5187123,4924209,9981761,10048324,8866114,12480076,12611918,12743760,13930595,13139542,13733217,12941908,12611918,12941395,12744272,12612174,12810066,13271385,13932394,4596017,6893367,8665148,8796988,8928316,8994364,9520189,10309438,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10309438,9717565,7350075,7481659,6694200,4069676,986384,1710364,1841437,1841949,1709850,986640,1184019,2828338,2959924,2039077,1512988,2368042,2959924,2959924,2959924,2170920],[4951500,14609142,16120316,16120060,13948117,1447195,1578781,1578781,2894132,3748928,4077893,4209222,4340808,4143429,4340808,4143429,3946307,4209479,4340808,4406601,5459032,5722202,5853532,3157304,5919581,5985118,5195860,5787996,5919325,5787995,5656410,5196116,5327702,5393238,5656409,5130067,4143685,2302506,3223096,4340808,4275272,2630696,1841693,1973280,1841436,1709850,1381145,3085604,4069418,7218747,7218747,7218747,7218747,7153211,4594221,3544872,3348006,3347749,4331820,6629686,11296582,12282699,11493960,8800065,12414284,12480332,12480076,12546125,12744016,12611918,12744016,12810066,12876115,12677967,12677967,12810066,13469533,13074006,12744016,13469532,14063466,4792882,6959158,8402492,8994365,9191485,10243645,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9717565,8402491,8270908,6825528,3807273,1052433,1710107,1841436,1841436,1249556,1052433,1775900,2959924,2762545,1512988,1710369,2959924,2959924,2959924,2959924,2433835],[5148620,12769517,15397625,16317181,15132390,1447195,1512989,1644575,2696752,3683135,3814721,4012100,4143685,3880514,3748928,3354427,3222840,3025717,2959924,3025717,3749184,3946306,3683391,2170920,4406600,4275271,4538443,4406600,4604236,3946050,4538443,4472393,4209478,3814720,3420219,3617598,2959924,1710367,2433836,4406601,4275271,2630440,1841693,1841693,1841436,1709850,1381145,3085603,3413285,7087418,7218747,7153211,5513010,3413286,3479078,4200747,6497846,9257024,12216394,12479820,12479820,12479820,12479820,12479820,12479820,12480076,12480076,12612174,12875859,12612174,12546125,13007957,12677967,12677967,12677968,12875859,13337434,13139542,12809809,13469276,13931623,4792882,6368055,8731196,9651773,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9651773,7810620,7415867,6497079,3676201,1052433,1709850,1841436,1775643,986640,1249556,1841693,2894131,1776161,1578782,2828338,2959924,2959924,2959924,2959924,2959924],[4885963,10338787,15528953,16317181,16316665,1447195,1447195,1644574,2302249,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,1512989,2894131,2959924,2959924,3025717,2959924,2959924,2959924,2959925,2959924,2959924,2959924,2959924,2959924,1644575,2039076,4406601,4209222,2565160,1841437,1841436,1775643,1644313,1381145,3413542,3348006,5184816,6628152,3807016,3479078,4331821,7483450,10703941,12414027,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12480076,12480076,12545869,12677967,12546125,12545869,12677967,12611918,12678223,12611918,12612175,12677967,12809553,12743760,13139543,13206106,4595761,6894393,10309438,10375230,10375230,10375230,10243646,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9849662,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10440766,9585981,7481915,7679035,6759992,3741737,1249555,1710107,1841437,1118226,986384,1709850,1841436,2565421,1578781,2105126,2959924,2959924,2959924,2959924,2959924,2959924],[4754635,9944801,15069175,16251644,16119544,2236451,1183765,1381401,2105127,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,1578781,2696752,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,1644574,1907747,5327445,5459031,3485493,1973280,1841436,1775643,1644057,1381143,4791602,4201004,3479078,3610151,3675944,7156534,11887945,12414027,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12480076,12545869,12677967,12611918,12545869,12546125,12545869,12546125,12611918,12941651,12810065,12612175,13007444,14326380,6107193,6435129,10375230,10375230,10375230,7485498,5647159,9127485,10375230,10375230,10375230,10375230,10375230,10375230,10375230,8667708,5975352,8273467,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10309438,9783357,7942204,7613243,6957369,3938603,1052433,1709850,1710107,1052432,1184019,1841436,1841436,1512988,1644574,2894130,2959924,2959924,2959924,2959924,2959924,2959924],[4885964,8696540,15791610,15988731,16119544,5921115,1118226,1184020,1381143,2368039,2565164,2828337,2894131,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,1512988,2630958,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2039333,1841697,5459031,5919325,4340290,2104353,1841436,1775643,1644313,1512215,6632509,9783871,4464429,4923952,11428168,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12480076,12612174,12546125,12545869,12480076,12545869,12480076,12480332,12677711,12545869,12809553,12677967,12875602,12941651,13140056,5450549,6040631,10309438,10375230,8470587,5450039,5056053,8602172,10375230,10375230,10375230,10375230,10375230,10375230,10243901,7682619,4990516,5646902,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9717565,7942204,7415867,6891576,3938603,920847,1709850,1183763,920847,1710107,1841436,1315349,1512988,2368043,2959924,2959924,2959924,2959924,2959924,2959924,2959924],[4754635,6265554,14543605,15528953,16120058,10395038,1118227,1184020,1315349,2368039,2368039,2368039,2368039,2433832,2565164,2696751,2894131,2959924,2959924,2959924,2959924,2959924,2959924,1578781,2368042,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2433835,1973283,5261652,5853532,4998478,2301731,1841436,1841436,1644313,1380629,6829630,12216906,9719875,11888458,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12545869,12546382,12480076,12612174,12480333,12677968,12546381,12611919,12611918,13007701,13996647,15381119,15644806,16304017,7489861,5712439,10375230,9258812,5384503,8016200,5318711,9193021,10375230,10375230,10375230,10375230,9127484,9652797,6369337,5318710,5187381,5581367,9718333,10375230,10375230,10375230,10375230,10375230,10375230,10374974,9651773,7810620,7415867,6628407,3610408,986640,1578521,986383,1118226,1841436,1775643,1117970,1776161,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924],[4754635,4885964,15660282,15331833,15528953,14540253,1118227,1249812,1249556,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368040,2433833,2565421,2828336,2894387,2959924,1776161,2104871,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2696752,1710367,4735565,5787739,5459287,3025455,1841437,1841436,1644057,1315091,6632253,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12546125,12611662,12480332,12480076,12546125,12876115,13930852,15909004,16370581,16700059,16700059,16700059,16700059,16700059,9002576,5515575,9915454,5843768,7752776,11174244,5515575,9915453,10375230,10375230,9784125,6238007,5318710,5056052,5384247,7945274,9324348,5384246,8273723,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9651773,7547451,7547451,6694200,3479079,986640,1249556,986640,1775643,1841436,1249812,986383,2828338,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924],[4754635,4754635,15594746,15134712,15594490,14408667,1118227,1184019,1315349,2170916,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1644573,1907490,2894130,2894131,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,1512988,4012354,5853532,5327444,3288627,1841436,1841436,1644057,1117713,7026493,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12480076,12480076,12480076,12611918,12611918,13007701,14194280,14721392,14721648,14853490,16568216,16700059,16700059,16700059,16700059,16700059,16700059,10450014,5449782,5384247,6173499,15318669,10516318,5515832,10375230,10243645,7223099,5778232,5252918,5318454,5318710,8930620,10375230,10375230,5318711,7748154,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9585981,7810620,7613243,6825528,3676201,920847,986896,1184019,1907487,1776156,920847,1381398,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924],[4885963,4754635,15200504,15463161,15200504,14211288,1118227,1118227,1249556,1907488,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1973280,1512729,2368039,2368039,2368039,2565163,2696750,2828337,2828338,2828338,2828338,2894130,2894131,2894131,2959924,1578781,3222838,5656409,5459031,3419443,1841436,1841436,1709850,920590,7486270,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12875859,14128230,14589806,14655599,14655599,14721648,14721648,14787697,15710595,16700059,16700059,16700059,16700059,16700059,16700059,10779490,5056052,5844024,14594949,16700059,10318940,5646904,7879738,5515575,5318710,6305084,6897216,5450039,9390140,10375230,10375230,10375230,5515575,7485498,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9585981,7613243,7416123,6562871,3479078,920591,920847,1644314,1841436,986640,986640,1841693,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924],[4885963,4820171,13360880,15791610,15857403,13750995,1841950,1118227,1249556,1578778,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2170660,1446935,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2565164,2959924,1710368,2302248,5722203,5656409,3682615,1973022,1841436,1775643,920591,7617852,12480076,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12743760,12810066,14194535,14655599,14655599,14655855,14655599,14721648,14721648,14787441,15051126,16634266,16700059,16700059,16700059,16700059,16700059,12687475,5845049,13081463,16700059,16700059,9727318,4990516,5318710,6172729,11699559,9332819,6041658,9652797,10375230,10375230,10375230,10375230,5318454,7551290,10375230,10375230,10375230,10375230,10375230,10375230,10309438,9783357,7613244,7679035,6431287,3348006,920590,1117970,1841693,1381398,1052433,1381142,1841693,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924,2959924],[4820171,4820171,10995686,15988732,15988987,15659508,4342339,1052434,1315349,1381399,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2302246,1315350,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1381400,1447194,5327445,5853788,4143424,2170145,1841693,1775643,920591,6764088,12479820,12480076,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12612174,13469533,13073493,14457964,14655599,14655599,14721392,14655855,14721392,14721648,14721648,14853234,16238224,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,13015922,8016456,13079663,15384461,9201235,5581367,10046782,10375230,10375230,10375230,10375230,10375230,5187382,8076603,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9717309,9059901,7547452,6497335,3413285,920847,1644057,1841693,986383,1052176,1841693,1907486,2499627,2499626,2828337,2959924,2959924,2959924,2959924,2959924,2959924],[4951756,4951499,8039385,15922939,16251644,15922937,6776680,920847,920847,1249556,2302245,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2302246,1249556,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1512985,1447194,5590617,5722203,4208960,2236195,1841436,1841436,920590,4466476,11954250,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12480076,12677967,12677967,12611918,14655599,14655599,14655599,14655599,14655599,14721648,14721648,14787441,14787697,16106123,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,15384462,8608846,5909560,9981246,10375230,10375230,10375230,10375230,10375230,9783869,5252918,8011067,10375230,10375230,10375230,10375230,10375230,10375230,10374974,9717565,8205116,7547451,6562871,3282469,920590,1578521,1578521,920847,1644058,1841436,1841693,2368040,2499370,2368040,2368039,2302503,1841952,1512987,1578781,2039077],[4820171,4754635,6396882,15397369,15528953,15594745,9803158,855054,920590,986384,1710106,1907229,2039072,2302246,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2302246,1249556,2236453,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1710365,1447193,5590616,5787996,4537926,2499110,1841436,1907486,986384,2037274,10968647,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12414027,12479820,12479820,12479820,12479820,12479820,12480076,12744017,12678223,12678223,14655599,14655599,14655599,14655599,14655855,14655855,14721392,14787441,14787441,15182967,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16239511,8805711,5384503,9784125,10375230,10375230,10375230,10375230,10375230,10375230,8470588,5187125,8864572,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9585981,7350075,7547451,6694199,3282469,920590,1315348,1512472,920847,1512728,1841436,1841436,2499370,2368039,2368039,2368039,1907745,1249814,5517098,8274216,5122341],[4754635,4754635,5739982,15266040,15791610,13755122,11184811,854798,855054,986383,1512727,1841436,1841436,1841436,1841436,1973023,2302246,2368039,2368039,2368039,2368039,2368039,2368039,2302246,1249813,2104866,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1841694,1184020,4472647,5787995,4867149,3222320,1841693,1841436,1183762,986383,9391940,12479820,12413771,11953480,8533819,6499897,4595247,4332845,5251630,12085322,12479820,12479820,12479820,12479820,12480076,12743760,12677968,12677968,14655599,14655599,14655599,14655599,14655855,14655855,14721648,14721392,14721648,14985076,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,9067854,5449782,8864828,10309438,10375230,10375230,10375230,10375230,10375230,10375230,6828858,5384247,10046781,10375230,10375230,10375230,10375230,10375230,10375230,10441022,9585981,7679036,7547451,6891320,3413798,855054,1117970,1775644,986383,1118226,1841436,1841436,2368040,2433833,2368039,2368039,2104868,1447192,10050603,14781474,14780449],[4820427,5148620,4885707,15069176,15594746,15660538,13882324,1381398,855054,986640,1315348,1775643,1841436,1841436,1841436,1841436,1841436,1841436,1907230,2170660,2302246,2302246,2368039,2368039,1249813,1973280,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,1973281,1184020,3354679,4998992,4867149,3485236,1841436,1841436,1249555,855054,8208704,8997185,4529710,3610664,3151140,3216676,3938345,3872809,3282213,8537407,12479820,12479820,12479820,12479820,12480076,12677968,13205592,12744016,14655599,14655599,14655599,14655599,14655599,14655855,14655855,14721392,14721392,15248504,16634008,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16634266,8739664,5384246,7748410,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,5778231,5712695,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10441023,9717565,7744827,7876155,6891576,3610664,855054,920591,1775900,1052433,986640,1841949,1907486,2368039,2499369,2433833,2368040,2433834,1578780,2431517,5779242,10114855],[5608654,5148876,4820171,10798821,16054524,15857403,11975618,4868427,854798,1052176,986383,1775643,1775643,1841436,1775643,1841436,1841436,1841436,1841436,1841436,1775643,1841437,2038816,2170660,1447192,1841694,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2104866,1249556,2368295,4998735,5130322,3551029,1841436,1907486,1315349,920591,7880256,7814463,4004907,3479335,3216676,5644083,7284283,6365751,3282469,7420729,12479820,12479820,12479820,12479820,12480076,13007701,12611918,13337178,14655599,14655855,14655599,14655599,14655855,14787441,14721648,14721648,14656111,15182711,16567702,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,15055241,5121845,6040887,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9784125,5515575,6434872,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9585981,7350331,7481659,6693944,3741736,920590,920590,1644057,1578264,920847,1447191,1841693,2433833,2368039,2368039,2368039,2368040,2433834,1907744,1381400,1315607],[5017548,4820171,4820171,7251158,16251644,16317437,15659508,11447726,920591,920847,986640,1644057,1841436,1841436,1775643,1841436,1841436,1775643,1775643,1775643,1775643,1775643,1775643,1841436,1381141,1315349,1907486,2104866,2302246,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2368039,2236452,1249556,1578779,4932942,5590616,3814715,1841694,2039072,1446935,920591,7223871,10048581,4792879,3216676,7021882,7218747,7218747,7021882,3282213,6566708,12479820,12479820,12479820,12479820,12545613,12810066,12744016,14062693,14655599,14655599,14655599,14655599,14655855,14655855,14721392,14721648,14655855,14853234,16106123,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,13475706,5187381,8667708,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,7419962,5449783,9783869,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9586237,7350331,7481659,6497079,3479335,920847,920590,1512471,1775643,855054,1052176,1775643,2170659,2302245,2368039,2368039,2433577,2499626,2368040,2368040,2170660],[4754635,5083341,4820171,4754635,14543605,15068919,15791610,13421773,1973278,855054,986383,1380885,1775643,1775643,1841436,1775643,1841436,1775643,1841436,1775643,1775643,1775643,1775643,1775643,1512471,1117969,1775643,1841436,1841436,1841693,1841436,1973280,2236196,2236453,2368038,2368038,2368039,2368039,2302246,1249813,1249813,4801356,5590617,4143424,1973279,1841693,1578264,855054,6304058,11231304,5450037,3151140,7218747,7218747,7218747,7152954,3282213,4924205,12414027,12479820,12479820,12479820,12545869,12677967,12677967,14457707,14655599,14655599,14655599,14655599,14655599,14655599,14655855,14721648,14853234,14721648,15775874,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,10910053,5384246,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10112317,5252662,5449782,10243902,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10309438,9586237,7350331,7547195,6694199,3610407,920591,920590,1117969,1775643,1249299,855054,1052433,1841436,1841436,1907486,2302245,2302246,2368039,2368039,2368039,2368039],[4885963,5017291,4754635,4754635,10995685,15791867,15726074,13619411,7302511,854798,855054,986383,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1841436,1775643,1775643,1578521,920847,1775643,1841436,1841436,1775643,1841436,1841436,1841436,1841436,1907486,1973279,2104866,2368038,2368039,1315350,1315606,5064785,5919325,4011581,2368037,1907486,1644057,855054,4334378,12151114,6500924,3216676,7021882,7218747,7218747,7218746,3479079,3544871,12282699,12479820,12479820,12479820,12545613,12809810,12677711,14457708,14590062,14524014,14589806,14655599,14655599,14655599,14655599,14656111,14787697,14853491,16040073,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,8344398,5712696,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10309438,6566199,4267566,4136237,5712437,8929852,10309438,10375230,10375230,10375230,10375230,10375230,10375230,9783357,8139580,7876155,6825784,3807274,855054,920590,855054,1709850,1644057,855054,855054,1512471,1775643,1841436,1775643,1841436,2039073,2236453,2368039,2368039],[4885707,4820171,4754635,4754635,5477326,16054524,16317437,15527923,12698050,854798,920590,920591,1578264,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,920590,1709850,1775643,1775643,1775643,1841436,1775643,1775643,1775643,1841436,1841436,1775643,1973279,2039073,1446936,1249814,5393494,5656410,4406597,2893612,1841693,1775643,986383,2233626,11691081,7486527,3413798,5578546,7218747,7218747,7218747,4200746,3348005,11625545,12479820,11099719,7420220,6369337,5121587,5121588,5779512,6436667,5713720,5713721,6108218,6305596,7028800,9197900,11630939,14524784,15117174,16040073,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16568473,6107451,6763322,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9587005,3742250,3742250,3676457,4333102,7942970,10375230,10375230,10375230,10375230,10375230,10375230,10309438,9586237,7547451,7679035,6694199,3413798,920590,1315348,1183762,920591,1578264,1249299,986384,986384,986383,1249299,1775643,1249299,986383,1117969,1183506,1710108],[4820171,4820171,4754635,4754635,4754635,14412021,16514301,16317437,14079702,2960174,854798,920847,920591,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,986640,1644057,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1841436,2039073,1578522,1315607,4867151,5656410,4867149,3485749,1841693,1775643,920591,1576980,10968391,8997186,4333358,4266283,7218747,7218747,7218747,5381682,3282469,9588548,8996416,4595761,4070957,4071214,4070957,4136750,5056822,5122358,5122358,5122358,5122358,5122358,5122358,5582392,5582648,5779513,10907733,16435602,16700059,16700059,16700059,16700059,16700059,16700059,16700059,15252364,5581367,8536636,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10243901,4988977,4135467,4135724,4069931,8665404,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9586237,7941947,7613243,6694455,3282213,920591,1709850,986383,855054,920590,1183763,1709850,1381141,920591,920591,1512471,1644057,1249298,4595495,2889244,1051919],[5017291,4754635,4754635,4754635,4754635,7054036,16120316,16251644,14409442,11579312,854798,920590,920847,1381142,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1117970,1315348,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,2039073,1776159,1578780,4275271,5524824,5459030,3682359,1841693,1775643,986640,1249042,9982532,10902855,5778488,3479078,7218747,7218747,7218747,6168885,3479335,7092030,4727090,4070701,4070957,4005421,4070957,4268079,5122358,5122358,5122358,5122358,5122358,5122358,5188406,8079682,10184016,8606023,8868679,16633494,16700059,16700059,16700059,16700059,16700059,16700059,16700059,13015415,5581111,9784125,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9585981,7481659,6956345,3676200,4791599,9914941,10375230,10375230,10375230,10375230,10375230,10375230,10309438,9651773,7679035,7679035,6562871,3479078,920591,1315348,986383,855054,855054,920590,920847,1446678,1644057,855054,1052176,1512471,5318950,12472094,12406558,9583656],[4820171,4820427,5148620,4754635,4754635,4754635,16185852,16185852,14609141,12960965,1446935,854798,855054,1052177,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1381142,920847,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1841436,1578521,1512986,3354682,5787996,5722202,3682615,1841693,1775643,1052177,1183505,9194307,12348235,6566716,3151140,6825017,7218747,7218747,6825017,3544871,6500923,5186613,4070957,4005421,4136750,4202286,4202542,5122358,5122358,5122358,5122358,5122358,5122614,5188150,5648184,6174267,14788212,15314553,16634266,16700059,16700059,16700059,16700059,16700059,16700059,16700059,9659735,5581367,10178109,10375230,10375230,10375230,10375230,10375230,10375230,10375230,7745083,7284539,5447730,3610407,7154233,10375230,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9651773,7810620,7481659,6497079,3413542,920590,920591,920590,855054,855054,855054,855054,855054,855054,855054,854798,855054,2233367,7024413,12078368,12340767],[4951756,4820171,4820171,4754635,4754635,4754635,11455720,14937590,15791867,15396337,6316129,854798,855054,855054,1249556,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1644057,920591,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1578264,1381400,2762543,5787996,5787995,3682615,1841436,1841436,1183763,920591,7683646,12479820,7354943,3151140,5644082,7218747,7218747,7218747,4135468,4398639,8536640,4333359,4005421,4005421,4005421,4202286,5122358,5122358,5122358,5122358,5187894,5516600,5845049,5713977,9461583,15116919,15973508,16699802,16700059,16700059,16700059,16700059,16700059,16700059,16700059,6501692,6238008,10375230,10375230,10375230,10375230,10375230,10375230,10375230,9980733,7415867,7284539,4397612,3413542,8204860,9059900,9585981,10112318,10375230,10309438,10375230,10309438,10309438,9651773,7679036,7416123,6694199,3282213,920590,920591,855054,854798,854798,854798,855054,1644309,4999475,1052432,1249555,855054,855054,855054,920590,3808032],[4754635,5083084,5148876,4754635,4754635,4754635,6791123,15594490,16185852,16120060,12698049,854798,263173,591625,854798,986384,1512471,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,920847,1644057,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1644057,1249814,2302248,5722203,5721946,3551029,1907486,1841436,1381142,920847,5451055,12480076,8800066,4464686,4725550,7218747,7218747,7284539,4725550,3544872,8340544,11033927,6435383,5186869,5055540,4727346,5779513,5582393,5779513,5845305,6305083,7751491,11499097,14590320,14787441,15182968,15644288,16634009,16700059,16700059,16700059,16700059,16700059,16700059,16567957,5252918,7551546,10243646,10243646,10309438,10309438,10375230,10375230,10375230,8862780,7284283,7087418,3479078,4135468,8796988,8862524,8862524,8862780,8928572,9125948,9257276,9454652,9849149,9454652,7284539,7284539,6694455,3282469,1379859,855054,460552,394502,723468,854798,854798,2696991,12827512,13945986,11445869,3946541,1512727,1052176,855054,854798],[4885963,5017292,4885963,4754635,4754635,4754635,4754635,13492208,15922939,15003383,15330027,2763051,197123,131586,131330,328966,789261,1117969,1578264,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1117969,1249555,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1249557,1841954,5919325,5787995,3616566,1973279,1841693,1710107,986384,3284257,12348491,11165512,5975352,3741479,7218747,7218747,7284283,5775412,3348006,5449523,12479820,12479820,12414028,11757387,11363915,13077348,13077348,13471846,14063722,14655599,14655599,14655599,14721392,14853490,15051126,16238223,16700059,16700059,16700059,16700059,16700059,16700059,16699545,13867630,4596017,8075835,9454653,9585981,9520189,9585981,9980477,9914686,10046525,8204860,7350075,6103605,3544871,6497335,8862524,8862524,8928572,8862524,8862780,8928316,8928572,8994364,9125948,8731196,7088185,5579058,4004137,3282469,2363675,460296,131586,198153,329481,394759,657675,854798,4604463,13945730,16051093,15129997,13879938,9603933,3946794,920590],[4951499,4885963,4754635,4754635,4754635,4754635,4754635,9484767,14018035,14214899,16580094,15132390,5789785,65793,65793,65793,65793,263173,789004,1052176,1644057,1775643,1775643,1775643,1775643,1775643,1512471,986384,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1118227,1841953,5787995,5787739,4011580,2104865,1907486,1841693,1052433,2233626,11691337,12414028,6566715,3348005,6890553,7218747,7284283,7218747,3413542,3610408,11887945,12479820,12545613,12546125,12611918,14589806,14655599,14655599,14655599,14655855,14655599,14721392,14721648,14721648,16172430,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16633752,9263692,4267566,8271930,8862524,8994108,8928316,8928572,8994364,9059900,9059900,7415867,7350075,4988209,3544871,8074042,8862780,8862780,9059900,8862524,8862524,8928316,8862780,8862780,7024697,4661552,3282469,3282469,3282213,3348006,2166552,131587,0,258,132359,593167,328964,131586,591881,1578516,14077314,14998411,15063948,15195533,16116629,13814401],[4820171,4754635,4885963,4754635,4754635,4754635,4754635,4951755,11718633,14477556,16054523,16645630,16645629,15987699,6250335,591881,0,65793,65537,131587,657418,986384,1578520,1775643,1775643,1775643,1775643,920591,1644057,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,920847,1776161,5590617,5656409,4406341,2367781,1973279,1841693,920847,1445908,11034697,12479820,6960701,3545127,6497079,7218747,7284283,7350075,3610407,3544872,9850690,12479820,12479820,12546125,12480076,14523757,14655599,14655599,14655855,14655599,14655599,14721648,14853491,15842438,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16700059,16567959,6041401,4530224,8796989,8796989,8796988,8796988,8862780,8862780,8862780,8205115,7284539,7416122,3676200,4135211,8731196,8994365,8862524,8928572,8862780,8796988,8928572,9059900,8928572,6565175,3939371,3282469,3282469,3282469,3282469,1838101,1,264460,66050,329741,198153,659992,526598,65793,65794,526089,5328181,15722130,15919507,16248214,15919507],[5148876,4754635,4754635,4754635,4754635,4754635,4754635,4754635,7645143,14018035,15923195,16711423,16645886,16645886,16514044,16250871,8092539,986895,65793,131330,0,65793,328966,920591,1512471,1775643,1775643,1249299,1249556,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,920847,2236456,5919581,5853789,5261651,2236195,1841693,1907486,986383,920847,9457731,12479820,8077376,4858673,5316146,7218747,7284283,7481659,3675944,3413542,8603199,12479820,12480076,12611918,12546125,14457964,14655599,14655855,14655599,14655599,14655599,14721648,15050869,16501908,16435859,16502166,16699802,16699802,16700059,16700059,16700059,16634266,15974281,5252405,5252146,8796989,8796989,8796989,8796989,8796988,8796989,8796988,7679035,7481659,7021882,3675944,6366775,8928316,8862524,8796988,9059900,8862780,8862780,8928572,8928572,8862524,8534587,5383474,3348006,3282469,3282469,3282469,1641234,131330,855567,1582901,4551064,9409431,7501691,856082,329222,65793,65793,0,855051,8091214,16642970,16511384],[4820171,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,7251158,13951986,14674933,16251388,16645887,16645886,16645886,16514301,15987699,11974326,394758,65793,65793,65794,131330,197124,789261,1446935,1644057,920847,1709850,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1052176,1710368,5787996,5787995,5524824,2564903,1907486,1841693,1381142,920847,6633270,12480076,10574406,5450037,3479079,7218747,6168886,4201003,3676200,5712437,11756873,12479820,12545869,12480076,12875602,14392427,14655855,14721392,14655855,14655599,14326122,13733216,15182711,14919027,14985332,14985076,15248760,15380603,16369808,16634266,16700059,16699802,13604460,4727089,6630711,8796989,8796989,8796989,8796988,8796989,8796989,8665404,7350075,7284283,5447475,3479335,7746105,8928316,8928572,8862780,8862780,8862780,8796988,8862780,8862524,8928572,8928316,8599356,6759992,3413542,3348006,3282469,1509905,590855,6908266,11383995,14412020,16120059,15462903,15264234,12895686,5856863,723720,65793,65793,65793,855050,5328181],[4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,6462674,15134968,15594489,16317437,16580094,16711679,16645886,16645630,16645886,14606046,2631720,65793,0,0,65537,65793,591881,855054,1315348,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1775643,1249299,1447195,5590617,5787739,5853788,2367781,1907486,1775643,1644314,920591,4006440,12348491,11757130,6632253,3544871,3413798,3938859,3938858,7288634,12085579,12479820,12479820,12479820,12479820,12546381,14128487,14655599,14655599,14655855,13864802,13865058,14194536,14787698,14787441,15116918,14919540,15182968,14919283,14985077,15249017,15908230,16237966,10118738,4595760,8271676,8731197,8731196,8796989,8796989,8796989,8796989,8270908,7284539,7350075,3610408,3807273,8731196,8796988,8862524,8928572,8994108,8862780,8862524,8862524,8796988,8928572,9059900,8533564,7284283,7284283,4660013,3282213,1050381,590855,10329501,14278112,15988731,16645631,16382973,16382973,15725817,15856371,15658992,12895684,3355443,263173,197379,197380],[4754635,4820171,4885963,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,6462674,13032431,16054523,15988731,16580094,16514557,16514558,16711423,16711422,14079702,4210752,65793,65537,0,262915,394756,1315599,3815208,4341295,4209711,5130808,6314817,6775109,4801845,3880749,1775643,1775643,1446678,1118227,5195859,5919581,5787995,2367780,1841436,1841436,1709850,986383,2233882,11888715,12348491,8142912,5777718,6500665,9194562,11953993,12479820,12479820,12479820,12479820,12480076,12480076,12480076,13667168,14655855,14655599,13996644,13930851,13667167,14655855,14787441,14721648,14853490,14721648,14787441,14853234,14590062,14787442,14853490,14326378,7291199,4398896,8205116,8139324,8731196,8796989,8796989,8796989,8796989,7481659,7284539,7284538,3807273,4726061,7547451,7942203,8336700,8599868,8796988,9059900,8928572,8862780,8862524,8928572,8928572,8468284,7218747,7284283,6431287,3479079,722184,328196,11184810,15988471,15857402,16579838,15660281,16382973,16185852,15594745,16054523,15396335,15330026,14869218,9342606,2960429],[4885963,4754635,4820171,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,6002896,10733028,14543605,15463161,16645886,16645886,16711679,16645630,16185336,14935011,7631988,0,0,0,131586,723720,3815203,11182952,14077572,14866826,13419645,10656615,2959653,1775643,1775643,1578264,1117970,4801358,5590617,5524824,2433318,1841436,1841693,1775643,1052176,920847,10048581,12479820,11757129,11888458,12479820,12479820,12479820,12479820,12479820,12479820,12479820,12480076,13273179,15122812,15849098,15251579,14457964,13601374,13667167,13930851,14655599,14655855,14721648,14721648,14721648,14787441,14721392,13007701,12875858,13007956,12744017,4530221,3872810,7350331,7350075,7876411,8007740,8204859,8731197,8796732,7284539,7350075,5644338,3741737,6694966,7481659,7876411,7810619,7810363,8139580,7744827,8270907,8336444,8862780,8862780,9125692,8599612,7218747,7350075,6497080,3676201,328196,196866,11382189,15528180,15791867,16251644,10338786,15003384,15857403,14412277,16251644,16054523,14608883,14936043,14474461,12764100],[4820171,4754635,4820171,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4820171,10207202,14871798,15134711,16645887,16711679,16711679,16711679,16711423,16711422,10197915,65793,0,0,65793,65793,657928,10590562,14143107,12169586,4144171,986383,1183506,1446934,920591,3288889,4341065,4340808,2696747,1841436,1841436,1841436,1446935,920590,5582897,12479820,12479820,12479820,12611918,12479820,12479820,12479820,12479820,13074262,15717511,16510614,16444565,16180112,16312211,16444822,16114063,13667679,13601118,14194023,14655855,14721392,14655855,14721648,14721648,14721648,14655599,12677967,12677711,12480076,11626058,4136236,5381683,7350331,7415867,7350075,7350075,7350075,7350331,7218747,7218747,7350075,4529453,3544871,8007739,7679035,7613244,8073787,8402492,7613243,8073788,8665404,7942203,7613243,7876411,8205116,8073532,7613243,7218747,6497080,3741737,196866,262659,12303291,16316923,15660538,14215156,5280205,4754635,5477070,11784169,14477813,15134456,15528953,15134711,14806262,14870507],[6331345,5017292,4820171,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,5017291,4754635,4754635,4754635,5411533,9221854,14412276,16120060,16514302,16645886,16711423,16711423,16645886,16448507,9605778,1710618,0,65537,0,65793,197123,460295,2301978,855054,920591,920591,855054,2894130,4340809,4406601,3091249,1841436,1841436,1841436,1709850,920591,1052434,10968391,12479820,12678224,13206874,13669474,15056763,16312467,16246418,16312468,16444566,16049811,15852434,15984019,15918483,15128459,15721105,15588494,15320448,14261098,14655855,16370324,16700059,16700059,16700059,16568216,15051384,12546125,12611918,12480332,11757386,6238009,4463405,7218747,7218747,7284539,7350075,7284283,7218747,7218747,7218747,7087418,3544615,4004138,7416123,7481659,7415867,7876411,7415867,7941947,8468028,7876411,8007739,7679035,7613243,7613243,7481659,7218747,7218747,6628152,3872810,393732,262402,12698049,16120057,15331833,15003383,5083084,4754635,4754635,4754635,4754635,7382486,13295344,15857403,16054523,15923195],[5542862,6002896,4951756,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4885963,4885963,5082828,4820171,5214413,5411534,5280205,7645143,14018035,15923195,15791866,16645886,16711679,16711423,16645886,16316921,12303291,3750457,0,0,65793,65793,65537,197380,657675,854798,855054,2433578,4340808,4209479,3683389,1841693,1841436,1841436,1709850,986640,854798,3547430,8012096,12030312,15522188,15720849,15786641,15852690,15523215,15325581,15457423,13547388,9270613,4272680,2561816,3810594,4204070,9335380,15918482,16115090,15649156,16502166,16700059,16700059,16700059,16700059,16106639,12810066,12677967,12546125,12480076,7223355,3479078,5972533,7218747,7218747,7284539,7415867,7284283,7218747,7218747,6103606,3479078,5709876,7218747,7218747,7218747,7350075,7284539,7481659,7679035,7876155,7481659,7416123,8073531,7613243,8073531,7218747,7218747,6497079,3610408,328452,262659,11776947,15594487,16185852,15003127,5608654,4951756,4820171,4754635,5083084,5148620,4754635,5148876,8039385,12901102],[6397138,5280205,4951755,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4754635,4820171,4754635,4754635,4820171,4820171,4820171,5083084,5608398,6265553,4951756,5345997,4951500,5345741,10338787,15660282,15726074,16711422,16711679,16711422,16580094,16580093,15132391,3947839,658960,657672,65793,65793,328966,789005,920590,1841953,4340808,4340808,4077891,2104866,1841436,1841436,1775643,920847,854798,2300190,7288894,9531994,15852690,16050324,15391630,15193997,7753033,4335145,1445134,525317,787975,722182,525317,657158,1116682,1379340,5715251,15193996,15654799,16706970,16700315,16700059,16700059,16700059,15974540,12941651,12611918,12611918,12480333,7026493,3938858,3610664,3807273,4266540,7153211,7350075,7218747,7218747,7218747,5119281,3544615,5250866,5512756,7218747,7218747,7218747,7218747,7218747,7350075,7350075,7481659,7350331,7218747,7284539,7350075,7218747,7218747,6431287,3544615,328195,459525,13619151,15725816,16448765,15726074,6988244,5674447,5214669,5148876,7973849,5017292,5345741,9681888,6988244,5805775],[8170713,6002896,5214412,4820171,4820171,4885964,4885963,4754635,4754635,4754635,4754635,4754635,4754635,4820171,4820427,4820171,5017548,4754635,4885963,5542862,5148876,4820171,5280205,4951755,4951499,5017292,5148876,11587049,15923195,16382973,16645886,16645886,16580094,16580094,16382973,14474975,4543069,1318955,659477,197637,131586,855054,1644317,4406601,4340808,4209221,2236452,2039073,1841436,1841436,1183506,920591,986383,1709850,3354665,6380866,4472880,723466,262659,459524,525317,459780,459524,525317,459781,263173,394758,591623,591109,1576718,4532776,13283960,15852690,16576153,16704667,16700059,16700059,16040333,12875859,12612174,12743760,9786181,6764093,6238267,3413798,3413542,3479078,3413286,3872554,5185073,6562871,7087418,3741737,3348005,3610408,5124405,5387831,4137004,5709619,6759480,7153211,7350075,7284283,7415867,7350075,7218747,7218747,7415867,7218747,7218747,6496823,3544871,262659,262915,14277081,15791610,15988731,14346484,7185365,5411533,5805775,5937104,6988500,5477326,8827868,9353439,7513815,10272994],[10076130,11849705,10273250,5148876,5214413,5017292,4885963,4820171,4820171,4885963,4820171,5083084,4885963,5017292,5542862,5083084,5542862,5871568,5280205,5280205,5148620,5739983,5674447,5280205,4886220,5214413,4885963,5345997,6199761,12441324,15857403,16251645,16645886,16711679,16645886,16645630,16251644,12831440,4611185,1383460,657675,1184020,1381401,4275015,4275015,4143685,2236195,1841436,1841436,1841436,1512471,920591,920590,1249556,1249555,460295,197379,65793,0,65537,65793,526861,592654,3553596,8750984,14409183,12174026,13092808,2565413,328451,591109,4797227,11638122,15523470,16576665,16773019,16700571,16106125,13205592,13271640,11299407,6567226,3020827,2758170,2560539,919050,1706770,2757151,3413543,3610408,3610408,4069676,3479078,3282213,2428956,2428955,2036246,7167556,9271897,7955021,4859441,5644339,6890553,7218747,7350331,7218747,7350331,7416123,7218747,7218747,6365751,3610407,262403,854797,15724527,16120316,15134712,13360880,7316950,5608655,5805775,5937103,7382485,6791124,8170714,8564955,9287646,6594003],[12441324,13820914,12506860,6134225,5674191,5739983,7316694,5871567,6068432,5214669,4820171,5017292,5148620,5739983,5674190,4951756,6199760,5543118,4951755,5083084,5411534,5674446,5214413,5411533,5148877,5083084,5542862,5017292,5740239,5083084,5214413,8499419,15200248,16645630,16777215,16777215,16777215,16645886,13426415,4147542,1315609,1447195,1512988,4077893,4340808,4275271,2367781,1907230,1841693,1841436,1775643,920847,855054,920847,723467,131586,65793,65793,65793,65793,65793,2569023,12635866,16185594,16645886,16645886,16448509,15988730,15527405,5592663,394243,788487,3351838,9991514,15523215,16313494,16773787,15911306,12875859,11102287,6830395,1379084,787975,525317,196866,262659,196866,393989,919050,1903894,3216933,3348006,3348006,1509649,1050379,919050,262403,524805,525062,1577232,5786935,10719589,8086351,5452342,5447474,7416123,7284539,7481659,7218747,7218747,5250354,3610407,328196,1578519,14737632,16054523,15331832,12441068,5674190,6725587,5608654,13426672,13558001,9353438,10404579,6791123,6002639,5805519],[16777215,15988987,16382973,11981290,10470116,11390184,10076129,11390183,10930149,10798565,8827612,9418975,11455719,10272995,11849961,11652584,12178410,12244203,11521512,11455719,11192806,11324391,11193063,11258599,11849961,11389927,11324391,11061478,11915754,12178411,11192806,11258599,11455720,12309740,16448509,16645886,16777215,16777215,16645630,7105649,1447195,1447195,1578781,3880513,4341064,4012100,2828077,2367783,1841436,1841436,1775643,1315348,986384,1052177,526088,0,131330,328965,526088,854798,854798,12961995,16448765,16777215,16777215,16777215,16580094,16580094,16579837,16119285,11645361,657415,722950,1643023,8938833,14601350,16379286,16443797,11765089,6699066,590853,1379085,919305,789002,4673625,3686214,1118226,196866,393989,262659,1050379,984587,1181709,328196,262659,197379,131329,196866,196866,328196,525061,262403,393732,3353632,12629365,14142340,11179370,7751238,7352639,5119793,3610151,3872810,590598,2434084,15066597,16580094,16580094,14674677,12178411,12572397,13492464,15068919,13229551,11981290,12046826,11915497,14477813,13032174],[16777215,16777215,16777215,16711679,16645630,16448766,15857403,15857403,14937591,15397625,15528697,15594746,15923195,16448765,16711679,16711423,16382973,16185852,16580094,15594489,16514558,16382973,16711422,16711679,16580094,16317437,16645886,16711679,16645886,16382973,16645886,16711679,16645887,16448765,16777215,16777215,16777215,16777215,16777215,8289666,1447195,1447195,1578781,3551805,4472394,4209479,2893870,1841693,1907229,1841693,1775643,1841436,1512727,1709850,1315092,1183762,1775643,1578520,920591,854798,854798,12698051,16580094,16777215,16777215,16777215,16645886,16711422,16777215,16777215,15066597,13092806,2039067,722951,1708815,8281163,14930826,12625779,7095614,787975,393988,262658,2828329,15527405,16579836,15461355,12763842,5197647,1842204,1118224,394245,460038,526087,262916,657930,3092529,5855577,1315860,460294,394245,262659,525062,459269,328195,525062,196866,3420192,9603929,12431732,12957049,9139544,3151395,393732,3486772,15461355,16711422,16777215,16777215,16777215,16711422,16711679,16777215,16777215,16711422,16645886,16777215,16777215,16711423],[16777215,16777215,16777215,16777215,16777215,16711679,16777215,16777215,16777215,16711423,16777215,16777215,16777215,16777215,16777215,16777215,16711679,16711422,16777215,16777215,16777215,16711422,16777215,16777215,16777215,16711422,16711422,16777215,16777215,16711422,16777215,16777215,16777215,16711423,16777215,16777215,16777215,16777215,16777215,10395297,1447195,1447195,1644575,3091510,4472394,4209479,3222836,1841436,1841436,1841436,1841436,1841436,1775900,1775643,1775643,1775643,1775643,1512471,920591,854798,854798,12829379,16711423,16777215,16777215,16777215,16711422,16777215,16777215,16777215,16711422,16185078,15921906,5460303,1445901,1248779,8806992,6700860,525316,393987,787975,3683638,15790320,16777215,16777215,16777215,16777215,16579836,15395562,9737364,2171169,657930,1644825,3684408,2236962,16250871,16777215,16711422,14079702,9934743,1381653,460294,591623,262659,328196,65537,131073,262659,262659,1116940,1509905,2166297,328196,4473668,14869218,16711422,16777215,16777215,16777215,16711423,16711679,16777215,16777215,16711679,16711679,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,11316144,1447195,1447195,1578781,2631215,4340808,4275015,3748926,2170402,1841436,1841436,1841436,1841436,1841436,1841436,1775643,1775643,1775643,1315092,920591,854798,854798,13816273,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,15527148,14474460,9472905,1182987,525828,197122,525316,459780,4078395,15856113,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16711422,15395562,6513507,11513775,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,11908533,3684408,1644566,526087,328195,131330,196866,131330,196866,393989,394758,6052956,15592941,16711422,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,14211289,1447195,1447195,1644575,2565422,4340808,4275272,3617340,1973022,1841436,1841693,1841436,1841436,1841436,1841436,1775643,1775643,1775643,1052176,920591,854798,854798,15395048,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16185078,14935011,12368569,855051,131328,723208,7631730,16448250,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16711422,13684944,7105644,3026220,1249040,1249810,2368548,1381653,723723,7303023,15724527,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,15592942,1447195,1447195,1512988,2368042,4340808,4340808,3946562,2236194,1841437,1841693,1841437,1841436,1775643,1775643,1775643,1775643,1578264,855054,855054,854798,2960173,16645629,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16514043,15724527,15395562,4144959,10592673,16514043,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,15790320,11447982,4737096,394758,2894892,11974326,16711422,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,1512988,1447195,1512988,2170663,4077893,4406601,4275271,2762539,1841436,1841436,1841693,1775643,1841436,1775643,1775643,1775643,1249556,920847,855054,855054,9079178,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16579836,15921906,16514043,16711422,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16514043,15329769,15790320,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,1973539,1447195,1512988,1841953,3223096,4340808,4406601,2828075,1907229,1907486,1907486,1841436,1775643,1775643,1775643,1709850,986383,855054,855054,986640,15066340,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,2499883,1447195,1512988,1644574,2959924,4275015,3946307,2433574,1907486,1841693,1841436,1841436,1775643,1775643,1775643,1315092,920591,855054,855054,4407362,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,2894641,1447195,1447195,1578781,2959924,2959924,2959924,1973280,1841693,1841436,1841436,1775643,1775643,1775643,1709850,920591,855054,854798,855054,15987442,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,5131858,1447195,1447195,1512988,2828594,2959924,2959924,2170660,1973279,1841436,1841693,1841436,1775643,1841436,1117969,920590,854798,854798,5065548,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,13553360,1447195,1447195,1512988,1776161,2959924,2959924,2368041,1841436,1907230,1973022,1841436,1775643,1512728,920591,854798,854798,854798,15856113,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,1447195,1447195,1447195,1512988,2433836,2959924,2630957,1907486,1841436,1907229,1841436,1644313,920591,920591,854798,854798,8947335,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,7434612,1447195,1447195,1512988,1578781,2236456,2828338,1973280,1841693,1841436,1775643,920591,920847,854798,854798,2433572,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16382458,3289399,1447195,1447195,1512988,1512989,1644574,1249812,1118226,1052433,920847,920847,854798,855054,920847,13684431,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,15658734,3026483,1447195,1447195,1447195,1447195,920847,920847,920847,920847,855054,855054,855054,13552844,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,1644831,1447195,1447195,1447195,920848,855054,855054,855055,855054,855054,14671326,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215],[16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,14671839,4934223,2236710,1249556,1184019,1249555,2960429,7170924,16711421,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215,16777215]] --------------------------------------------------------------------------------