diff --git a/index.html b/index.html index 9efadb5..329c040 100644 --- a/index.html +++ b/index.html @@ -9,6 +9,7 @@ + diff --git a/js/lib/game.js b/js/lib/game.js index d510c70..190282a 100644 --- a/js/lib/game.js +++ b/js/lib/game.js @@ -52,12 +52,18 @@ Game.prototype._getRobot = function(a, b) { return this._cells[a][b]; }; +Game.prototype._removeRobot = function(a, b) { + this._cells[a][b] = null; +}; + Game.prototype._setRobot = function(a, b, robot) { this._cells[a][b] = robot; robot.setCoordinates(a, b); }; Game.prototype.kill = function(robot) { + var coordinates = robot.getCoordinates(); + this._removeRobot(coordinates.a, coordinates.b); var index = this._robots.indexOf(robot); this._robots.splice(index, 1); this.emit('death', robot); @@ -75,7 +81,7 @@ Game.prototype.isFirstStep = function() { return this._step === 1; }; -Game.prototype.nextStep = function() { +Game.prototype.nextTick = function() { this._step++; if (this.isFirstStep()) { @@ -83,8 +89,9 @@ Game.prototype.nextStep = function() { return; } + var self = this; this.getRobots().forEach(function(robot) { - robot.nextStep(); + robot.nextTick(); }); }; diff --git a/js/lib/instructions.js b/js/lib/instructions.js index 78d72d7..d73a18b 100644 --- a/js/lib/instructions.js +++ b/js/lib/instructions.js @@ -1,20 +1,62 @@ -module.exports = { +var instructions = { + 'init': { + costs: 0, + execute: function(game, robot, args) {} + }, 'rotate': { costs: 1, execute: function(game, robot, args) { robot.rotate(args[0]); - return args; + } + }, + 'move': { + costs: 1, + execute: function(game, robot, args) { + robot.move(); + } + }, + 'scan': { + costs: 1, + execute: function(game, robot, args) { + var coordinates = game._getCoordinatesInFrontOf(robot); + var otherRobot = game._getRobot(coordinates.a, coordinates.b); + if (!otherRobot) { + return ['empty']; + } + + return (otherRobot.getPlayer() === robot.getPlayer()) + ? 'friend' + : 'enemy'; } }, 'transfer': { costs: function(game, robot, args) { + return 1; }, - execute: function() { + execute: function(game, robot, args) { + var coordinates = game._getCoordinatesInFrontOf(robot); + var otherRobot = game._getRobot(coordinates.a, coordinates.b); + if (!otherRobot) { + return; + } + + var sourceProgram = robot._code[args[0]]; + otherRobot._code = $.extend(true, {}, otherRobot._code); + + var destProgram = {}; + otherRobot._code[otherRobot._currentProgram] = destProgram; + for (var key in sourceProgram) { + destProgram[key] = sourceProgram[key]; + } + + otherRobot._currentArgs = []; + otherRobot._currentInstruction = 'init'; + otherRobot._remainingCycles = 0; }, }, 'build': { costs: function(game, robot, args) { - return 10; + return 2; //if (args[0] === 'builder') { //return 10; //} @@ -26,7 +68,7 @@ module.exports = { //return new Error('build: unknown type: ' + args[0]); }, execute: function(game, robot, args) { - var coordinates = game.getCoordinatesInFrontOf(robot); + game.buildRobot(robot); }, } }; diff --git a/js/lib/robot.js b/js/lib/robot.js index 38e7616..f4b8985 100644 --- a/js/lib/robot.js +++ b/js/lib/robot.js @@ -2,7 +2,11 @@ function Robot() { this._a = null; this._b = null; this._rotation = null; - this._operation = null; + + this._currentProgram = 'main'; + this._currentArgs = []; + this._currentInstruction = 'init'; + this._remainingCycles = 0; this._code = null; this._game = null; @@ -62,6 +66,21 @@ Robot.prototype.rotate = function(direction) { this._game.emit('rotate', this); }; +Robot.prototype.move = function() { + var newCoordinates = this._game._getCoordinatesInFrontOf(this); + if (this._game._getRobot(newCoordinates.a, newCoordinates.b)) { + return; + } + + var oldCoordinates = this.getCoordinates(); + this.setCoordinates(newCoordinates.a, newCoordinates.b); + + this._game._removeRobot(oldCoordinates.a, oldCoordinates.b); + this._game._setRobot(newCoordinates.a, newCoordinates.b, this); + + this._game.emit('move', this, oldCoordinates); +}; + Robot.prototype.build = function() { this._game.buildRobot(this); }; @@ -72,24 +91,63 @@ Robot.prototype.scan = function() { //if ( }; -Robot.prototype.nextStep = function() { - var operation = this._operation || 'ready'; - this._invoke(operation); +Robot._getCallbackName = function(instruction) { + var firstLetter = instruction.substr(0, 1); + var remainingLetters = instruction.substr(1); + return 'after' + firstLetter.toUpperCase() + remainingLetters; }; -Robot.prototype._invoke = function(operation) { - var name = operation.substr(0, 1).toUpperCase() + operation.substr(1); - var r = this._code.main['after' + name].apply({}, this._args); - this._args = []; +Robot.prototype.nextTick = function() { + if (this._remainingCycles > 0) { + this._remainingCycles--; + return; + } + + var executeFn = instructions[this._currentInstruction].execute; + var resultArgs = executeFn.call({}, this._game, this, this._currentArgs); + if (resultArgs) { + resultArgs = [].concat(resultArgs); + } + + var callbackName = Robot._getCallbackName(this._currentInstruction); + var callbackFn = this._code[this._currentProgram][callbackName]; + + if (!callbackFn) { + console.log('missing callback: ' + callbackName); + this._commitSuicide(); + return; + } + + var nextArgs = callbackFn.apply({}, resultArgs || []); + if (!nextArgs) { + console.log('emtpy method: ' + callbackName); + this._commitSuicide(); + return; + } + var nextInstruction = nextArgs.shift(); + + if (!(nextInstruction in instructions)) { + console.log('unknown instruction: ' + nextInstruction); + this._commitSuicide(); + return; + } + + var costs = instructions[nextInstruction].costs; + if (typeof costs === 'function') { + costs = costs.call({}, this._game, this); + } - if (!r) { + if (costs instanceof Error) { + console.log('costs error: ' + costs.message); this._commitSuicide(); return; } - this._operation = r.shift(); - this[this._operation].apply(this, r); + this._remainingCycles = costs; + this._currentInstruction = nextInstruction; + this._currentArgs = nextArgs; + //console.log(this._currentInstruction, this._currentArgs); }; Robot.prototype._commitSuicide = function() { diff --git a/js/lib/visualizer.js b/js/lib/visualizer.js index 2e5fa0c..65c7211 100644 --- a/js/lib/visualizer.js +++ b/js/lib/visualizer.js @@ -17,6 +17,7 @@ Visualizer.prototype.render = function(game) { this._renderGrid(); game.on('rotate', this._handleRotate.bind(this)); + game.on('move', this._handleMove.bind(this)); game.on('spawn', this._handleSpawn.bind(this)); game.on('death', this._handleDeath.bind(this)); }; @@ -69,6 +70,17 @@ Visualizer.prototype._handleRotate = function(robot) { .addClass('rotate_' + rotation); }; +Visualizer.prototype._handleMove = function(robot, oldCoordinates) { + var newCoordinates = robot.getCoordinates(); + + var $oldTd = this._getTd(oldCoordinates); + var $newTd = this._getTd(newCoordinates); + + $newTd.append($oldTd.children().remove()); + $newTd.attr('class', $oldTd.attr('class')); + $oldTd.attr('class', ''); +}; + Visualizer.prototype._handleSpawn = function(robot) { var coordinates = robot.getCoordinates(); var $td = this._getTd(coordinates); diff --git a/js/main.js b/js/main.js index c131c39..58057fb 100644 --- a/js/main.js +++ b/js/main.js @@ -1,10 +1,25 @@ $(function() { var TIMEOUT = 0; + var programs = {}; + Program.load('js/program/flooder.js', function(program) { + programs.red = program; + onProgramLoad(); + }); Program.load('js/program/spinner.js', function(program) { - var game = Game.create(32); - game.add('red', program); - game.add('blue', program); + programs.blue = program; + onProgramLoad(); + }); + + + function onProgramLoad() { + if (Object.keys(programs).length < 2) { + return; + } + + var game = Game.create(20); + game.add('red', programs.red); + game.add('blue', programs.blue); var visualizer = Visualizer.create($('.js_container')); visualizer.render(game); @@ -12,7 +27,7 @@ $(function() { var interval; function continueGame() { interval = setInterval(function() { - game.nextStep(); + game.nextTick(); }, TIMEOUT); } @@ -32,23 +47,5 @@ $(function() { }); continueGame(); - }); - - //var grid = Grid.create(8); - //var visualizer = Visualizer.create(); - - //var SIZE = 8; - //var html = ['']; - - //for (var a = 0; a < SIZE; a++) { - //html.push(''); - //for (var b = 0; b < SIZE; b++) { - //html.push(''); - //} - //html.push(''); - //} - - //html.push('
' + a + ', ' + b + '
'); - - //$('.js_grid_container').html(html.join('\n')); + }; }); diff --git a/js/program/flooder.js b/js/program/flooder.js index a5e676b..b0eb9ff 100644 --- a/js/program/flooder.js +++ b/js/program/flooder.js @@ -1,5 +1,5 @@ main: { - afterReady: function() { + afterInit: function() { return ['scan']; }, afterScan: function(result) { @@ -13,16 +13,29 @@ main: { return ['rotate', 'right']; }, - afterBuild: function() { - return ['transfer', 'main']; - }, afterTransfer: function() { return ['rotate', 'right']; }, + afterBuild: function() { + return ['rotate', 'right']; + }, afterRotate: function() { return ['scan']; } }, virus: { - afterReady: function() {} + afterInit: function() { + return ['scan']; + }, + afterScan: function(result) { + if (result === 'empty') { + return; + } + + if (result === 'friend') { + return ['transfer', 'main']; + } + + return; + }, } diff --git a/js/program/spinner.js b/js/program/spinner.js index 6908553..349a609 100644 --- a/js/program/spinner.js +++ b/js/program/spinner.js @@ -1,11 +1,11 @@ main: { - afterReady: function() { + afterInit: function() { return ['build']; }, afterBuild: function() { - return ['rotate', 'right']; + return ['rotate', 'left']; }, afterRotate: function() { return ['build']; - } + }, }