"use strict"; const kWidth = 15; const kHeight = 10; class Client { async start() { let self = this; terminal.setTitle("Xmas 2016"); terminal.setSendKeyEvents(true); terminal.split([{name: "terminal", style: "text-align: center"}]); self.send({action: "ready"}); core.register("key", function(event) { if (event.type == "keydown") { switch (event.keyCode) { case 37: self.requestMove(-1, 0); break; case 38: self.requestMove(0, -1); break; case 39: self.requestMove(1, 0); break; case 40: self.requestMove(0, 1); break; } } }); core.register("onMessage", function(sender, message) { if (message.action == "display") { terminal.cork(); terminal.clear(); terminal.print(message.board); terminal.uncork(); } }); } async send(message) { (await core.getService("server")).postMessage(message); } async requestMove(dx, dy) { this.send({action: "move", delta: [dx, dy]}); } } class Server { constructor() { this.players = {}; } async start() { let self = this; core.register("onMessage", function(sender, message) { if (!self.players[sender.index]) { self.players[sender.index] = [Math.floor(Math.random() * 8) + 1, 8]; } switch (message.action) { case "move": self.move(sender.index, message.delta); self.redisplay(); break; case "ready": self.redisplay(); break; } }); core.register("onSessionEnd", function(session) { delete self.players[session.index]; self.redisplay(); }); } occupied(position) { if (position[0] < 1 || position[1] < 1 || position[0] >= kWidth - 1 || position[1] >= kHeight - 1) { return true; } if (Object.values(this.players).some(x => position[0] == x[0] && position[1] == x[1])) { return true; } } move(index, delta) { let newPosition = [ this.players[index][0] + delta[0], this.players[index][1] + delta[1], ]; let pushPosition = [ this.players[index][0] + 2 * delta[0], this.players[index][1] + 2 * delta[1], ]; if (!this.occupied(newPosition)) { this.players[index] = newPosition; } else if (this.occupied(newPosition) && !this.occupied(pushPosition)) { for (var i in this.players) { if (this.players[i][0] == newPosition[0] && this.players[i][1] == newPosition[1]) { this.players[i] = pushPosition; } } this.players[index] = newPosition; } } redisplay() { core.broadcast({action: "display", board: this.getBoard()}); } getBoard() { let board = [ "┌─────────────┐", "│ . │", "│ .#. │", "│ .%##. │", "│ .##%##. │", "│ .%###%##. │", "│ .##%###%##. │", "│.#%##%###%##.│", "│ | │", "└─────────────┘", ]; let merry = false; let colors = board.map(x => x.split("").map(y => '#fff')); for (let i in this.players) { let player = this.players[i]; merry = merry || (player[0] == 7 && player[1] == 1); let character = player[0] == 7 && player[1] == 1 ? '*' : '@'; board[player[1]] = board[player[1]].slice(0, player[0]) + character + board[player[1]].slice(player[0] + 1); } if (merry) { for (let i = 0; i < colors.length; i++) { for (let j = 0; j < colors[i].length; j++) { switch (board[i].charAt(j)) { case '#': case '.': colors[i][j] = '#080'; break; case '%': colors[i][j] = '#f00'; break; case '|': colors[i][j] = '#880'; break; case '*': colors[i][j] = '#ff0'; break; case '@': { const palette = ['#f88', '#8f8', '#88f', '#fff']; colors[i][j] = palette[(i * colors.length + j) % palette.length]; } break; } } } } let result = board.map((r, row) => r.split("").map((v, column) => ({style: "color: " + colors[row][column], value: v})).concat(["\n"])); if (merry) { result.push("Merry Christmas!"); } else { result.push("use ←↑→↓"); } return result; } } if (imports.terminal) { new Client().start().catch(terminal.print); } else { new Server().start().catch(print); }