Commits

Anonymous committed 98e858a

Initial import of Gemooy in HTML5.

  • Participants

Comments (0)

Files changed (3)

+<!DOCTYPE html>
+<head>
+  <meta charset="utf-8">
+  <title>Gemooy</title>
+  <script src="http://code.jquery.com/jquery-1.8.1.min.js"></script>
+  <script src="../src/playfield.js"></script>
+  <script src="../src/gemooy.js"></script>
+  <script>
+$(document).ready(function() {
+    var eso = GemooyController($('#canvas')[0]);
+    $('#load').click(function() {
+        eso.load($('#program'));
+    });
+    $('#start').click(function() {
+        eso.start();
+    });
+    $('#stop').click(function() {
+        eso.stop();
+    });
+});
+  </script>
+  <style>
+#canvas { border: 1px solid blue; }
+  </style>
+</head>
+<body>
+
+<h1>Gemooy</h1>
+
+<canvas id="canvas" width="400" height="400">
+Your browser doesn't support displaying an HTML5 canvas.
+</canvas>
+
+<span>
+<textarea id="program" rows="10" cols="40">
+%   @@   @@
+#  @  $    @
+       @
+#      #
+#
+       @
+#     # #
+#    #
+    @     @
+    @     @@
+#  @ @    @
+@   @   @
+</textarea>
+
+<button id="load">Load</button>
+<button id="start">Start</button>
+<button id="stop">Stop</button>
+
+</body>
+function GemooyController(canvas) {
+    var self = {};
+    var interval_id;
+
+    var p = Playfield();
+    var ip_x;
+    var ip_y;
+    var ip_dx;
+    var ip_dy;
+    var dp_x;
+    var dp_y;
+
+    self.draw = function() {
+        var ctx = canvas.getContext('2d');
+
+        ctx.clearRect(0, 0, canvas.width, canvas.height);
+        ctx.textBaseline = "top";
+
+        var height = 20;
+        ctx.font = height + "px monospace";
+        var width = ctx.measureText("@").width;
+
+        ctx.fillStyle = "#ff5080";
+        ctx.fillRect(ip_x * width, ip_y * height, width, height);
+
+        ctx.fillStyle = "#50ff80";
+        ctx.fillRect(dp_x * width, dp_y * height, width, height);
+
+        ctx.fillStyle = "black";
+        p.foreach(function (x, y, value) {
+            ctx.fillText(value, x * width, y * height);
+        });
+    }
+
+    var rotate_clockwise = function() {
+        if (ip_dx === 0 && ip_dy === -1) {
+            ip_dx = 1; ip_dy = -1;
+        } else if (ip_dx === 1 && ip_dy === -1) {
+            ip_dx = 1; ip_dy = 0;
+        } else if (ip_dx === 1 && ip_dy === 0) {
+            ip_dx = 1; ip_dy = 1;
+        } else if (ip_dx === 1 && ip_dy === 1) {
+            ip_dx = 0; ip_dy = 1;
+        } else if (ip_dx === 0 && ip_dy === 1) {
+            ip_dx = -1; ip_dy = 1;
+        } else if (ip_dx === -1 && ip_dy === 1) {
+            ip_dx = -1; ip_dy = 0;
+        } else if (ip_dx === -1 && ip_dy === 0) {
+            ip_dx = -1; ip_dy = -1;
+        } else if (ip_dx === -1 && ip_dy === -1) {
+            ip_dx = 0; ip_dy = -1;
+        }
+    }
+
+    var rotate_counterclockwise = function() {
+        if (ip_dx === 0 && ip_dy === -1) {
+            ip_dx = -1; ip_dy = -1;
+        } else if (ip_dx === -1 && ip_dy === -1) {
+            ip_dx = -1; ip_dy = 0;
+        } else if (ip_dx === -1 && ip_dy === 0) {
+            ip_dx = -1; ip_dy = 1;
+        } else if (ip_dx === -1 && ip_dy === 1) {
+            ip_dx = 0; ip_dy = 1;
+        } else if (ip_dx === 0 && ip_dy === 1) {
+            ip_dx = 1; ip_dy = 1;
+        } else if (ip_dx === 1 && ip_dy === 1) {
+            ip_dx = 1; ip_dy = 0;
+        } else if (ip_dx === 1 && ip_dy === 0) {
+            ip_dx = 1; ip_dy = -1;
+        } else if (ip_dx === 1 && ip_dy === -1) {
+            ip_dx = 0; ip_dy = -1;
+        }
+    }
+
+    var is_headed = function(dx, dy) {
+        return ip_dx === dx && ip_dy === dy;
+    }
+
+    var advance = function() {
+        ip_x += ip_dx;
+        ip_y += ip_dy;
+    }
+
+    var increment = function(x, y) {
+        var data = p.get(x, y);
+        if (data === undefined) {
+            data = '#';
+        } else if (data === '#') {
+            data = '@';
+        } else if (data === '@') {
+            data = undefined;
+        }
+        p.put(x, y, data);
+    }
+
+    var decrement = function(x, y) {
+        var data = p.get(x, y);
+        if (data === undefined) {
+            data = '@';
+        } else if (data === '@') {
+            data = '#';
+        } else if (data === '#') {
+            data = undefined;
+        }
+        p.put(x, y, data);
+    }
+
+    self.step = function() {
+        var instr = p.get(ip_x, ip_y);
+
+        if (instr === '@') {
+            var data = p.get(dp_x, dp_y);
+            if (data === undefined) {
+                rotate_clockwise();
+            } else if (data == '#') {
+                rotate_counterclockwise();
+            }
+        } else if (instr === '#') {
+            if (is_headed(0, -1)) {
+                dp_y--;
+                advance();
+            } else if (is_headed(0, 1)) {
+                dp_y++;
+                advance();
+            } else if (is_headed(1, 0)) {
+                dp_x++;
+                advance();
+            } else if (is_headed(-1, 0)) {
+                dp_x--;
+                advance();
+            } else if (is_headed(-1, -1) || is_headed(1, -1)) {
+                increment(dp_x, dp_y);
+            } else if (is_headed(-1, 1) || is_headed(1, 1)) {
+                decrement(dp_x, dp_y);
+            }
+        }
+
+        advance();
+        self.draw();
+    }
+
+    self.start = function() {
+        if (interval_id !== undefined)
+            return;
+        self.step();
+        interval_id = setInterval(self.step, 100);
+    }
+
+    self.stop = function() {
+        if (interval_id === undefined)
+            return;
+        clearInterval(interval_id);
+        interval_id = undefined;
+    }
+
+    self.load = function(textarea) {
+        self.stop();
+        p.load(0, 0, textarea.val());
+        p.foreach(function (x, y, value) {
+            if (value === '$') {
+                ip_x = x;
+                ip_y = y;
+                return ' ';
+            } else if (value === '%') {
+                dp_x = x;
+                dp_y = y;
+                return ' ';
+            }
+        });
+        ip_dx = 1;
+        ip_dy = 1;
+        self.draw();
+    }
+
+    return self;
+}
+function Playfield() {
+    var self = {}
+    var store = {}
+    self.min_x = undefined;
+    self.min_y = undefined;
+    self.max_x = undefined;
+    self.max_y = undefined;
+
+    /*
+     * Cells are undefined if they were never written to.
+     */
+    self.get = function(x, y) {
+        return store[x+','+y];
+    }
+
+    self.put = function(x, y, value) {
+        if (self.min_x === undefined || x < self.min_x) self.min_x = x;
+        if (self.max_x === undefined || x > self.max_x) self.max_x = x;
+        if (self.min_y === undefined || y < self.min_y) self.min_y = y;
+        if (self.max_y === undefined || y > self.max_y) self.max_y = y;
+        store[x+','+y] = value;
+    }
+
+    /*
+     * Load a string into the playfield.
+     * The string may be multiline, with newline (ASCII 10)
+     * characters delimiting lines.  ASCII 13 is ignored.
+     */
+    self.load = function(x, y, string) {
+        var lx = x;
+        var ly = y;
+        for (var i = 0; i < string.length; i++) {
+            var c = string.charAt(i);
+            if (c === '\n') {
+                lx = x;
+                ly++;
+            } else if (c === ' ') {
+                self.put(lx, ly, undefined);
+                lx++;
+            } else if (c === '\r') {
+            } else {
+                self.put(lx, ly, c);
+                lx++;
+            }
+        }
+    }
+
+    /*
+     * fun is a callback which takes three parameters:
+     * x, y, and value.
+     * This function ensures a particular order.
+     */
+    self.foreach = function(fun) {
+        for (var y = self.min_y; y <= self.max_y; y++) {
+            for (var x = self.min_x; x <= self.max_x; x++) {
+                var key = x+','+y;
+                var value = store[key];
+                if (value === undefined)
+                    continue;
+                var result = fun(x, y, value);
+                if (result !== undefined) {
+                    if (result === ' ') {
+                        result = undefined;
+                    }
+                    self.put(x, y, result);
+                }
+            }
+        }
+    }
+
+    return self;
+}