MediaWiki:Gadget-Global-Formicarium.js
Jump to navigation
Jump to search
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
* Formicarium is an implementation of Langton's ant
* Documentation: https://www.mediawiki.org/wiki/Template:Formicarium
* Author: Felipe Schenone (User:Sophivorus)
* License: GNU General Public License (http://www.gnu.org/licenses/gpl.html)
*/
var Formicarium = {
messages: {
'de': {
'ant-button': 'Ameise',
'ant-button-tooltip': 'Ameise hinzufügen oder entfernen',
'cell-button': 'Zelle',
'cell-button-tooltip': 'Zelle hinzufügen oder entfernen',
'move-button': 'Bewegen',
'move-button-tooltip': 'board bewegen',
'zoom-in-button': 'Einzoomen',
'zoom-in-button-tooltip': 'Einzoomen',
'zoom-out-button': 'Auszoomen',
'zoom-out-button-tooltip': 'Auszoomen',
'grid-button': 'Raster',
'grid-button-tooltip': 'Raster',
'reset-button': 'Zurücksetzen',
'reset-button-tooltip': 'Zurücksetzen',
'previous-generation-button': 'Zurück',
'previous-generation-button-tooltip': 'Vorherige Generation',
'play-button': 'Abspielen',
'play-button-tooltip': 'Abspielen',
'pause-button': 'Pause',
'pause-button-tooltip': 'Pause',
'next-generation-button': 'Weiter',
'next-generation-button-tooltip': 'Nächste Generation',
},
'en': {
'ant-button': 'Ant',
'ant-button-tooltip': 'Add or remove ants',
'cell-button': 'Cell',
'cell-button-tooltip': 'Add or remove cells',
'move-button': 'Move',
'move-button-tooltip': 'Move the board',
'zoom-in-button': 'Zoom in',
'zoom-in-button-tooltip': 'Zoom in',
'zoom-out-button': 'Zoom out',
'zoom-out-button-tooltip': 'Zoom out',
'grid-button': 'Grid',
'grid-button-tooltip': 'Grid',
'reset-button': 'Reset',
'reset-button-tooltip': 'Reset',
'previous-generation-button': 'Previous',
'previous-generation-button-tooltip': 'Previous generation',
'play-button': 'Play',
'play-button-tooltip': 'Play',
'pause-button': 'Pause',
'pause-button-tooltip': 'Pause',
'next-generation-button': 'Next',
'next-generation-button-tooltip': 'Next generation',
'generation-counter': 'Generation ',
'cell-counter': 'Cells ',
'ant-counter': 'Ants ',
},
'es': {
'ant-button': 'Hormiga',
'ant-button-tooltip': 'Agregar o quitar hormigas',
'cell-button': 'Celda',
'cell-button-tooltip': 'Agregar o quitar celdas',
'move-button': 'Mover',
'move-button-tooltip': 'Mover el tablero',
'zoom-in-button': 'Acercar',
'zoom-in-button-tooltip': 'Acercar',
'zoom-out-button': 'Alejar',
'zoom-out-button-tooltip': 'Alejar',
'grid-button': 'Grilla',
'grid-button-tooltip': 'Grilla',
'reset-button': 'Reiniciar',
'reset-button-tooltip': 'Reiniciar',
'previous-generation-button': 'Anterior',
'previous-generation-button-tooltip': 'Generación anterior',
'play-button': 'Reproducir',
'play-button-tooltip': 'Reproducir',
'pause-button': 'Pausar',
'pause-button-tooltip': 'Pausar',
'next-generation-button': 'Siguiente',
'next-generation-button-tooltip': 'Generación siguiente',
'generation-counter': 'Generación ',
'cell-counter': 'Celdas ',
'ant-counter': 'Hormigas ',
},
'fr': {
'ant-button': 'Fourmi',
'ant-button-tooltip': 'Ajouter ou enlever des fourmis',
'cell-button': 'Cellule',
'cell-button-tooltip': 'Ajouter ou enlever des cellules',
'move-button': 'Déplacer',
'move-button-tooltip': 'Déplacer la carte',
'zoom-in-button': 'Se rapprocher',
'zoom-in-button-tooltip': 'Se rapprocher',
'zoom-out-button': "S'éloigner",
'zoom-out-button-tooltip': "S'éloigner",
'grid-button': 'Grille',
'grid-button-tooltip': 'Grille',
'reset-button': 'Recommencer',
'reset-button-tooltip': 'Recommencer',
'previous-generation-button': 'Anterieur',
'previous-generation-button-tooltip': 'Génération anterieure',
'play-button': 'Reproduire',
'play-button-tooltip': 'Reproduire',
'pause-button': 'Mettre sur pause',
'pause-button-tooltip': 'Mettre sur pause',
'next-generation-button': 'Suivant',
'next-generation-button-tooltip': 'Generation suivante',
},
'it': {
'ant-button': 'Formica',
'ant-button-tooltip': 'Aggiungere o rimuovere le formiche',
'cell-button': 'Cellula',
'cell-button-tooltip': 'Aggiungere o rimuovere le cellule',
'move-button': 'Spostare',
'move-button-tooltip': "Spostare l'asse",
'zoom-in-button': 'Ingrandire',
'zoom-in-button-tooltip': 'Ingrandire',
'zoom-out-button': 'Rimpicciolire',
'zoom-out-button-tooltip': 'Rimpicciolire',
'grid-button': 'Griglia',
'grid-button-tooltip': 'Griglia',
'reset-button': 'Reset',
'reset-button-tooltip': 'Reset',
'previous-generation-button': 'Precedente',
'previous-generation-button-tooltip': 'Generazione precedente',
'play-button': 'Giocare',
'play-button-tooltip': 'Giocare',
'pause-button': 'Pausa',
'pause-button-tooltip': 'Pausa',
'next-generation-button': 'Il prossimo',
'next-generation-button-tooltip': 'Generazione successiva',
},
'pl': {
'ant-button': 'Mrówka',
'ant-button-tooltip': 'Dodaj lub odejmij mrówki',
'cell-button': 'Komórka',
'cell-button-tooltip': 'Dodaj lub odejmij komórki',
'move-button': 'Przejdź dalej',
'move-button-tooltip': "Przestaw planszę",
'zoom-in-button': 'Przybliż',
'zoom-in-button-tooltip': 'Przybliż',
'zoom-out-button': 'Oddal',
'zoom-out-button-tooltip': 'Oddal',
'grid-button': 'Siatka',
'grid-button-tooltip': 'Siatka',
'reset-button': 'Reset',
'reset-button-tooltip': 'Reset',
'previous-generation-button': 'Poprzedni',
'previous-generation-button-tooltip': 'Poprzednie pokolenie',
'play-button': 'Odtwórz',
'play-button-tooltip': 'Odtwórz',
'pause-button': 'Zatrzymaj',
'pause-button-tooltip': 'Zatrzymaj',
'next-generation-button': 'Dalej',
'next-generation-button-tooltip': 'Następne pokolenie',
},
},
/**
* Initialisation script
*/
init: function () {
// Set the interface language
var lang = mw.config.get( 'wgUserLanguage' );
if ( ! ( lang in Formicarium.messages ) ) {
lang = 'en'; // Fallback to English
}
mw.messages.set( Formicarium.messages[ lang ] );
$( '.Formicarium' ).each( function () {
var gui = new Formicarium.GUI( this ),
board = new Formicarium.Board( gui ),
game = new Formicarium.Game( board ),
mouse = new Formicarium.Mouse( board );
touch = new Formicarium.Touch( board );
gui.bindEvents( board, game, mouse, touch );
board.init();
if ( $( this ).data( 'autoplay' ) ) {
game.play();
}
});
},
/**
* Graphical User Interface
*/
GUI: function ( wrapper ) {
this.wrapper = $( wrapper );
this.container = $( '<div>' ).addClass( 'FormicariumContainer' );
this.canvas = $( '<canvas>' ).addClass( 'FormicariumCanvas' );
this.generationCounter = $( '<span>' ).addClass( 'FormicariumCounter FormicariumGenerationCounter' ).text( mw.message( 'generation-counter' ) + 0 );
this.cellCounter = $( '<span>' ).addClass( 'FormicariumCounter FormicariumCellCounter' ).text( mw.message( 'cell-counter' ) + 0 );
this.antCounter = $( '<span>' ).addClass( 'FormicariumCounter FormicariumAntCounter' ).text( mw.message( 'ant-counter' ) + 0 );
this.menu = $( '<div>' ).addClass( 'FormicariumMenu' );
this.zoomInButton = $( '<img>' ).attr({
'class': 'FormicariumButton FormicariumZoomInButton',
'src': '//upload.wikimedia.org/wikipedia/commons/2/2e/WikiWidgetZoomInButton.png',
'title': mw.message( 'zoom-in-button-tooltip' ),
'alt': mw.message( 'zoom-in-button' )
});
this.zoomOutButton = $( '<img>' ).attr({
'class': 'FormicariumButton FormicariumZoomOutButton',
'src': '//upload.wikimedia.org/wikipedia/commons/6/63/WikiWidgetZoomOutButton.png',
'title': mw.message( 'zoom-out-button-tooltip' ),
'alt': mw.message( 'zoom-out-button' )
});
this.gridButton = $( '<img>' ).attr({
'class': 'FormicariumButton FormicariumGridButton',
'src': '//upload.wikimedia.org/wikipedia/commons/a/a9/WikiWidgetGridButton.png',
'title': mw.message( 'grid-button-tooltip' ),
'alt': mw.message( 'grid-button' )
});
this.resetButton = $( '<img>' ).attr({
'class': 'FormicariumButton FormicariumResetButton',
'src': '//upload.wikimedia.org/wikipedia/commons/0/0e/WikiWidgetResetButton.png',
'title': mw.message( 'reset-button-tooltip' ),
'alt': mw.message( 'reset-button' )
});
this.previousGenerationButton = $( '<img>' ).attr({
'class': 'FormicariumButton FormicariumPreviousGenerationButton',
'src': '//upload.wikimedia.org/wikipedia/commons/c/c3/WikiWidgetPreviousFrameButton.png',
'title': mw.message( 'previous-generation-button-tooltip' ),
'alt': mw.message( 'previous-generation-button' )
});
this.playButton = $( '<img>' ).attr({
'class': 'FormicariumButton FormicariumPlayButton',
'src': '//upload.wikimedia.org/wikipedia/commons/b/b8/WikiWidgetPlayButton.png',
'title': mw.message( 'play-button-tooltip' ),
'alt': mw.message( 'play-button' )
});
this.pauseButton = $( '<img>' ).attr({
'class': 'FormicariumButton FormicariumPauseButton',
'src': '//upload.wikimedia.org/wikipedia/commons/6/6e/WikiWidgetPauseButton.png',
'title': mw.message( 'pause-button-tooltip' ),
'alt': mw.message( 'pause-button' )
}).hide(); // The pause button starts hidden
this.nextGenerationButton = $( '<img>' ).attr({
'class': 'FormicariumButton FormicariumNextGenerationButton',
'src': '//upload.wikimedia.org/wikipedia/commons/b/bf/WikiWidgetNextFrameButton.png',
'title': mw.message( 'next-generation-button-tooltip' ),
'alt': mw.message( 'next-generation-button' )
});
// Put it all together
this.menu.append(
this.zoomInButton,
this.zoomOutButton,
this.gridButton,
this.resetButton,
this.previousGenerationButton,
this.playButton,
this.pauseButton,
this.nextGenerationButton
);
this.container.append(
this.canvas,
this.menu,
this.generationCounter,
this.cellCounter,
this.antCounter
);
this.wrapper.html( this.container );
this.bindEvents = function ( board, game, mouse, touch ) {
// Board events
this.zoomOutButton.click( function () { board.zoomOut(); } );
this.zoomInButton.click( function () { board.zoomIn(); } );
this.gridButton.click( function () { board.toggleGrid(); } );
// Game events
this.resetButton.click( function () { game.reset(); } );
this.previousGenerationButton.click( function () { game.previousGeneration(); } );
this.playButton.click( function () { game.play(); } );
this.pauseButton.click( function () { game.pause(); } );
this.nextGenerationButton.click( function () { game.nextGeneration(); } );
// Mouse events
this.canvas.mousedown( function ( event ) { mouse.down( event ) } );
this.canvas.mousemove( function ( event ) { mouse.move( event ) } );
this.canvas.mouseup( function ( event ) { mouse.up( event ) } );
// Touch events
this.canvas.on( 'touchstart', function ( event ) { touch.start( event ) } );
this.canvas.on( 'touchmove', function ( event ) { touch.move( event ) } );
this.canvas.on( 'touchend', function ( event ) { touch.end( event ) } );
};
},
Board: function ( gui ) {
this.gui = gui;
this.canvas = this.gui.canvas[0];
this.context = this.canvas.getContext( '2d' );
this.width = this.canvas.width;
this.height = this.canvas.height;
this.centerX = 0;
this.centerY = 0;
this.cellSize = 4;
this.xCells = Math.floor( this.width / this.cellSize );
this.yCells = Math.floor( this.height / this.cellSize );
this.grid = false;
this.cellCounter = 0;
this.antCounter = 0;
this.oldCells = [];
this.cells = [];
this.ants = [];
/**
* Constructor
*/
this.init = function () {
this.oldCells = [];
this.cells = [];
this.ants = [];
this.centerX = 0;
this.centerY = 0;
this.setCellCounter( 0 );
this.setAntCounter( 0 );
var wrapper = this.gui.wrapper,
width = wrapper.data( 'width' ),
height = wrapper.data( 'height' ),
cells = wrapper.data( 'cells' ),
ants = wrapper.data( 'ants' ),
zoom = wrapper.data( 'zoom' ),
grid = wrapper.data( 'grid' );
if ( width ) {
this.setWidth( width );
}
if ( height ) {
this.setHeight( height );
}
if ( cells ) {
cells = cells.replace( /\s/g, '' ).split( ';' );
for ( var c in cells ) {
coords = cells[ c ].split( ',' );
x = coords[0];
y = coords[1];
this.addCell( x, y );
}
}
if ( ants ) {
ants = ants.replace( /\s/g, '' ).split( ';' );
for ( var a in ants ) {
coords = ants[ a ].split( ',' );
x = coords[0];
y = coords[1];
this.addAnt( x, y );
}
}
if ( zoom ) {
this.setCellSize( zoom );
}
if ( grid ) {
this.grid = true;
}
this.refill();
};
/* Getters */
this.getXcells = function () {
return Math.floor( this.width / this.cellSize );
};
this.getYcells = function () {
return Math.floor( this.height / this.cellSize );
};
this.getCell = function ( x, y ) {
var i, cell;
for ( i in this.cells ) {
cell = this.cells[ i ];
if ( cell.x === x && cell.y === y ) {
return cell;
}
}
return null;
};
this.getOldCell = function ( x, y ) {
var i, cell;
for ( i in this.oldCells ) {
cell = this.oldCells[ i ];
if ( cell.x === x && cell.y === y ) {
return cell;
}
}
return null;
};
this.getAnt = function ( x, y ) {
var i, ant;
for ( i in this.ants ) {
ant = this.ants[ i ];
if ( ant.x === x && ant.y === y ) {
return ant;
}
}
return null;
};
/* Setters */
this.setCellCounter = function ( value ) {
this.cellCounter = value;
this.gui.cellCounter.text( mw.message( 'cell-counter' ) + value );
};
this.setAntCounter = function ( value ) {
this.antCounter = value;
this.gui.antCounter.text( mw.message( 'ant-counter' ) + value );
};
this.setWidth = function ( value ) {
this.width = parseInt( value );
this.canvas.setAttribute( 'width', value );
this.xCells = this.getXcells();
};
this.setHeight = function ( value ) {
this.height = parseInt( value );
this.canvas.setAttribute( 'height', value );
this.yCells = this.getYcells();
};
this.setCellSize = function ( value ) {
this.cellSize = parseInt( value );
this.xCells = this.getXcells();
this.yCells = this.getYcells();
};
/* Actions */
this.zoomIn = function () {
if ( this.cellSize === 32 ) {
return;
}
this.setCellSize( this.cellSize * 2 );
this.refill();
};
this.zoomOut = function () {
if ( this.cellSize === 1 ) {
return;
}
this.setCellSize( this.cellSize / 2 );
this.refill();
};
this.toggleGrid = function () {
this.grid = this.grid ? false : true;
this.refill();
};
this.drawGrid = function () {
if ( this.cellSize < 4 ) {
return; // Cells are too small for the grid
}
this.context.beginPath();
for ( var x = 0; x <= this.xCells; x++ ) {
this.context.moveTo( x * this.cellSize - 0.5, 0 ); // The 0.5 avoids getting blury lines
this.context.lineTo( x * this.cellSize - 0.5, this.height );
}
for ( var y = 0; y <= this.yCells; y++ ) {
this.context.moveTo( 0, y * this.cellSize - 0.5 );
this.context.lineTo( this.width, y * this.cellSize - 0.5 );
}
this.context.strokeStyle = '#333';
this.context.stroke();
};
this.fill = function () {
var i, cell, ant;
for ( i in this.cells ) {
cell = this.cells[ i ];
this.fillCell( cell.x, cell.y, cell.color );
}
for ( i in this.ants ) {
ant = this.ants[ i ];
this.fillCell( ant.x, ant.y, ant.color );
}
if ( this.grid ) {
this.drawGrid();
}
};
this.clear = function () {
this.context.clearRect( 0, 0, this.canvas.width, this.canvas.height );
};
this.refill = function () {
this.clear();
this.fill();
};
this.fillCell = function ( x, y, color ) {
var minX = this.centerX - Math.floor( this.xCells / 2 ),
minY = this.centerY - Math.floor( this.yCells / 2 ),
maxX = minX + this.xCells,
maxY = minY + this.yCells;
if ( x < minX || y < minY || x > maxX || y > maxY ) {
return; // If the cell is beyond view, don't draw it
}
var rectX = Math.abs( this.centerX - Math.floor( this.xCells / 2 ) - x ) * this.cellSize,
rectY = Math.abs( this.centerY - Math.floor( this.yCells / 2 ) - y ) * this.cellSize,
rectW = this.cellSize,
rectH = this.cellSize;
this.context.fillStyle = color;
this.context.fillRect( rectX, rectY, rectW, rectH );
};
this.addCell = function ( x, y, color ) {
x = parseInt( x );
y = parseInt( y );
var cell = this.getCell( x, y );
var index = this.cells.indexOf( cell );
if ( index === -1 ) {
color = color ? color : 'white';
this.fillCell( x, y, color );
this.cells.push({ 'x': x, 'y': y, 'color': color });
this.setCellCounter( this.cellCounter + 1 );
}
};
this.addOldCell = function ( x, y, color ) {
var cell = this.getOldCell( x, y );
var index = this.oldCells.indexOf( cell );
if ( index === -1 ) {
color = color ? color : 'white';
this.fillCell( x, y, color );
this.oldCells.push({ 'x': x, 'y': y, 'color': color });
}
};
this.removeCell = function ( x, y ) {
var cell = this.getCell( x, y ),
index = this.cells.indexOf( cell );
if ( index > -1 ) {
this.cells.splice( index, 1 );
this.setCellCounter( this.cellCounter - 1 );
}
};
this.removeOldCell = function ( x, y ) {
var cell = this.getOldCell( x, y ),
index = this.oldCells.indexOf( cell );
if ( index > -1 ) {
this.oldCells.splice( index, 1 );
}
};
this.addAnt = function ( x, y ) {
x = parseInt( x );
y = parseInt( y );
var ant = new Formicarium.Ant( this, x, y );
this.ants.push( ant );
this.setAntCounter( this.antCounter + 1 );
};
this.removeAnt = function ( x, y ) {
x = parseInt( x );
y = parseInt( y );
var ant = this.getAnt( x, y );
var index = this.ants.indexOf( ant );
this.ants.splice( index, 1 );
this.setAntCounter( this.antCounter - 1 );
};
},
Game: function ( board ) {
this.board = board;
this.playing = false;
this.generationCounter = 0;
/* Setters */
this.setGenerationCounter = function ( value ) {
this.generationCounter = value;
this.board.gui.generationCounter.text( mw.message( 'generation-counter' ) + value );
};
/* Actions */
this.previousGeneration = function () {
this.board.oldCells = this.board.cells.slice(); // Clone the array
for ( var i in this.board.ants ) {
this.board.ants[ i ].undoRoutine();
}
this.board.refill();
this.setGenerationCounter( this.generationCounter - 1 );
};
this.nextGeneration = function () {
this.board.oldCells = this.board.cells.slice(); // Clone the array
for ( var i in this.board.ants ) {
this.board.ants[ i ].doRoutine();
}
this.board.refill();
this.setGenerationCounter( this.generationCounter + 1 );
};
this.reset = function () {
// Reset the board
this.board.init();
// Reset the game
this.pause();
this.setGenerationCounter( 0 );
};
this.play = function () {
if ( this.playing ) {
return; // The game is already playing
}
var game = this;
this.playing = setInterval( function () { game.nextGeneration(); }, 1 ); // The interval id is stored in the playing property
this.board.gui.playButton.hide();
this.board.gui.pauseButton.show();
};
this.pause = function () {
if ( !this.playing ) {
return; // The game is already paused
}
clearInterval( this.playing );
this.playing = false;
this.board.gui.playButton.show();
this.board.gui.pauseButton.hide();
};
},
Mouse: function ( board ) {
this.board = board;
/**
* The position relative to the origin of the coordinate system of the board (in cells, not pixels)
*/
this.oldX = null;
this.oldY = null;
this.newX = null;
this.newY = null;
this.state = null; // up or down
this.dragged = false;
/* Getters */
this.getX = function ( event ) {
var offsetX = event.pageX - $( event.target ).offset().left - 1, // The -1 is to correct a minor displacement
newX = this.board.centerX - Math.floor( this.board.xCells / 2 ) + Math.floor( offsetX / this.board.cellSize );
return newX;
};
this.getY = function ( event ) {
var offsetY = event.pageY - $( event.target ).offset().top - 2, // The -2 is to correct a minor displacement
newY = this.board.centerY - Math.floor( this.board.yCells / 2 ) + Math.floor( offsetY / this.board.cellSize );
return newY;
};
/* Event handlers */
this.up = function ( event ) {
this.state = 'up';
if ( !this.dragged ) {
var x = this.newX,
y = this.newY,
ant = this.board.getAnt( x, y );
if ( ant ) {
this.board.removeAnt( x, y );
} else {
this.board.addAnt( x, y );
}
this.board.refill();
}
this.dragged = false;
};
this.move = function ( event ) {
if ( this.state === 'down' ) {
this.oldX = this.newX;
this.oldY = this.newY;
this.newX = this.getX( event );
this.newY = this.getY( event );
if ( this.newX !== this.oldX || this.newY !== this.oldY ) {
this.dragged = true;
this.board.centerX += this.oldX - this.newX;
this.board.centerY += this.oldY - this.newY;
this.board.refill();
// Bugfix: without the following, the board flickers when moving, not sure why
this.newX = this.getX( event );
this.newY = this.getY( event );
}
}
};
this.down = function ( event ) {
this.state = 'down';
this.newX = this.getX( event );
this.newY = this.getY( event );
};
},
Touch: function ( board ) {
this.board = board;
// The distance from the origin of the coordinate system in virtual pixels (not real ones)
this.newX = null;
this.newX = null;
this.oldX = null;
this.oldY = null;
this.moved = false;
/**
* Getters
*/
this.getX = function ( event ) {
var offsetX = event.originalEvent.changedTouches[0].pageX - $( event.target ).offset().left,
newX = this.board.centerX - Math.floor( this.board.xCells / 2 ) + Math.floor( offsetX / this.board.cellSize );
return newX;
};
this.getY = function ( event ) {
var offsetY = event.originalEvent.changedTouches[0].pageY - $( event.target ).offset().top,
newY = this.board.centerY - Math.floor( this.board.yCells / 2 ) + Math.floor( offsetY / this.board.cellSize );
return newY;
};
/**
* Event handlers
*/
this.start = function ( event ) {
this.newX = this.getX( event );
this.newY = this.getY( event );
};
this.move = function ( event ) {
this.oldX = this.newX;
this.oldY = this.newY;
this.newX = this.getX( event );
this.newY = this.getY( event );
this.board.centerX += this.oldX - this.newX;
this.board.centerY += this.oldY - this.newY;
this.board.refill();
// Bugfix: without the following, the board flickers when moving, not sure why
this.newX = this.getX( event );
this.newY = this.getY( event );
this.moved = true;
event.preventDefault();
};
this.end = function ( event ) {
this.moved = false;
};
},
Ant: function ( board, x, y, color, direction ) {
this.board = board;
this.x = x ? x : 0;
this.y = y ? y : 0;
this.color = color ? color : 'red';
this.direction = direction ? direction : 'N';
this.getCell = function () {
return this.board.getCell( this.x, this.y );
};
this.getOldCell = function () {
return this.board.getOldCell( this.x, this.y );
};
this.addCell = function ( color ) {
this.board.addCell( this.x, this.y, color );
return this;
};
this.removeCell = function () {
this.board.removeCell( this.x, this.y );
return this;
};
this.addOldCell = function ( color ) {
this.board.addOldCell( this.x, this.y, color );
return this;
};
this.removeOldCell = function () {
this.board.removeOldCell( this.x, this.y );
return this;
};
this.turnLeft = function () {
if ( this.direction === 'N' ) {
this.direction = 'W';
} else if ( this.direction === 'W' ) {
this.direction = 'S';
} else if ( this.direction === 'S' ) {
this.direction = 'E';
} else if ( this.direction === 'E' ) {
this.direction = 'N';
}
return this;
};
this.turnRight = function () {
if ( this.direction === 'N' ) {
this.direction = 'E';
} else if ( this.direction === 'W' ) {
this.direction = 'N';
} else if ( this.direction === 'S' ) {
this.direction = 'W';
} else if ( this.direction === 'E' ) {
this.direction = 'S';
}
return this;
};
this.moveBack = function () {
if ( this.direction === 'N' ) {
this.y--;
} else if ( this.direction === 'W' ) {
this.x++;
} else if ( this.direction === 'S' ) {
this.y++;
} else if ( this.direction === 'E' ) {
this.x--;
}
return this;
};
this.moveForward = function () {
if ( this.direction === 'N' ) {
this.y++;
} else if ( this.direction === 'W' ) {
this.x--;
} else if ( this.direction === 'S' ) {
this.y--;
} else if ( this.direction === 'E' ) {
this.x++;
}
return this;
};
this.doRoutine = function () {
var cell = this.getOldCell();
if ( cell ) {
this.removeCell().turnRight();
} else {
this.addCell().turnLeft();
}
this.moveForward();
};
this.undoRoutine = function () {
this.moveBack();
var cell = this.getOldCell();
if ( cell ) {
this.removeCell().turnRight();
} else {
this.addCell().turnLeft();
}
};
}
};
$( Formicarium.init );