diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000000000000000000000000000000000000..87dbf9ac3d82336ccee46d3fb414fbf3dc5024af
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,19 @@
+{
+ "esnext": true,
+ "indent": 2,
+ "maxlen": 80,
+ "freeze": true,
+ "camelcase": true,
+ "unused": true,
+ "eqnull": true,
+ "proto": true,
+ "supernew": true,
+ "noyield": true,
+ "evil": true,
+ "node": true,
+ "boss": true,
+ "expr": true,
+ "loopfunc": true,
+ "white": true,
+ "maxdepth": 4
+}
diff --git a/index.html b/index.html
index c85e844dcec57520c4be4dea9a32b9ec889cf42d..31d1727d8fc9eb45a7de3599149f05f478bd8470 100644
--- a/index.html
+++ b/index.html
@@ -5,6 +5,11 @@
2048
+
+
+
+
+
diff --git a/js/application.js b/js/application.js
new file mode 100644
index 0000000000000000000000000000000000000000..dde4cc4d9337bfd0175d42e50f05cdf90858d8ae
--- /dev/null
+++ b/js/application.js
@@ -0,0 +1,4 @@
+document.addEventListener("DOMContentLoaded", function () {
+ var actuator = new HTMLActuator;
+ var manager = new GameManager(4, actuator);
+});
diff --git a/js/game_manager.js b/js/game_manager.js
new file mode 100644
index 0000000000000000000000000000000000000000..b1a2de3b4175cf47554de7c383162c2bc52dcfe8
--- /dev/null
+++ b/js/game_manager.js
@@ -0,0 +1,83 @@
+function GameManager(size, actuator) {
+ this.size = size; // Grid size
+ this.actuator = actuator;
+
+ this.startTiles = 2;
+ this.grid = [];
+
+ this.setup();
+}
+
+// Set up the game
+GameManager.prototype.setup = function () {
+ this.buildGrid();
+ this.addStartTiles();
+
+ // Update the actuator
+ this.update();
+};
+
+// Build a grid of the specified size
+GameManager.prototype.buildGrid = function () {
+ for (var y = 0; y < this.size; y++) {
+ this.grid[y] = [];
+ for (var x = 0; x < this.size; x++) {
+ this.grid[y].push(null);
+ }
+ }
+};
+
+// Set up the initial tiles to start the game with
+GameManager.prototype.addStartTiles = function () {
+ for (var i = 0; i < this.startTiles; i++) {
+ this.addTile();
+ }
+};
+
+// Adds a tile in a random position
+GameManager.prototype.addTile = function () {
+ this.insertTile(new Tile(this.randomCell()));
+};
+
+// Find the first available random position
+GameManager.prototype.randomCell = function () {
+ // TODO: build a map of available positions and choose from it
+ var self = this;
+
+ var position;
+
+ function randomPosition() {
+ return Math.floor(Math.random() * self.size);
+ }
+
+ do {
+ position = {
+ x: randomPosition(),
+ y: randomPosition()
+ };
+ } while (this.cellOccupied(position));
+
+ return position;
+};
+
+// Check if the specified cell is taken
+GameManager.prototype.cellOccupied = function (cell) {
+ return !!this.grid[cell.x][cell.y];
+};
+
+// Insert a tile at the specified position
+GameManager.prototype.insertTile = function (tile) {
+ this.grid[tile.x][tile.y] = tile;
+};
+
+// Sends the updated grid to the actuator
+GameManager.prototype.update = function () {
+ this.actuator.update(this.grid);
+};
+
+// Move the grid in the specified direction
+GameManager.prototype.move = function (direction) {
+ // 0: up, 1: right, 2:down, 3: left
+
+ this.update();
+};
diff --git a/js/html_actuator.js b/js/html_actuator.js
new file mode 100644
index 0000000000000000000000000000000000000000..c3594019daa888ba9646481976977040a9f7d7e5
--- /dev/null
+++ b/js/html_actuator.js
@@ -0,0 +1,13 @@
+function HTMLActuator() {
+
+}
+
+HTMLActuator.prototype.update = function (grid) {
+ // Temporary debug visualizer
+ grid.forEach(function (row) {
+ var mapped = row.map(function (tile) {
+ return tile ? tile.value : " ";
+ }).join(" | ");
+ console.log(mapped);
+ });
+};
diff --git a/js/tile.js b/js/tile.js
new file mode 100644
index 0000000000000000000000000000000000000000..25664e5076af52a96c5a549a9c875dd8c7b4e616
--- /dev/null
+++ b/js/tile.js
@@ -0,0 +1,7 @@
+function Tile(position, value) {
+ this.x = position.x;
+ this.y = position.y;
+ this.value = value || 2;
+
+ this.previousPosition = null;
+}