It looks like this is a web page, not a feed. I looked for a feed associated with this page, but couldn't find one. Please enter the address of your feed to validate.

Source: https://okey-net.com/

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Maintenance - Moota.co</title>
  5. <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Permanent+Marker">
  6. <style type="text/css">
  7. body {
  8. background-color: black;
  9. }
  10.  
  11. #pacman {
  12. height: 470px;
  13. width: 382px;
  14. border-radius: 5px;
  15. margin: 20px auto;
  16. }
  17.  
  18. #shim {
  19. font-family: 'Permanent Marker', cursive;
  20. position: absolute;
  21. visibility: hidden
  22. }
  23.  
  24. h1 {
  25. font-family: 'Permanent Marker', cursive;
  26. text-align: center;
  27. color: yellow;
  28. }
  29.  
  30. body {
  31. width: 342px;
  32. margin: 0px auto;
  33. font-family: sans-serif;
  34. }
  35.  
  36. p {
  37. text-decoration: none;
  38. color: #0000FF;
  39. }
  40. </style>
  41. </head>
  42. <body>
  43. <div id="shim">shim for font face</div>
  44. <h1>Baran</h1>
  45. <div id="pacman"></div>
  46.  
  47. <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
  48. <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  49. <script type="text/javascript">
  50. /*jslint browser: true, undef: true, eqeqeq: true, nomen: true, white: true */
  51. /*global window: false, document: false */
  52.  
  53. /*
  54. * fix looped audio
  55. * add fruits + levels
  56. * fix what happens when a ghost is eaten (should go back to base)
  57. * do proper ghost mechanics (blinky/wimpy etc)
  58. */
  59.  
  60. var NONE        = 4,
  61.    UP          = 3,
  62.    LEFT        = 2,
  63.    DOWN        = 1,
  64.    RIGHT       = 11,
  65.    WAITING     = 5,
  66.    PAUSE       = 6,
  67.    PLAYING     = 7,
  68.    COUNTDOWN   = 8,
  69.    EATEN_PAUSE = 9,
  70.    DYING       = 10,
  71.    Pacman      = {};
  72.  
  73. Pacman.FPS = 30;
  74.  
  75. Pacman.Ghost = function (game, map, colour) {
  76.  
  77.    var position  = null,
  78.        direction = null,
  79.        eatable   = null,
  80.        eaten     = null,
  81.        due       = null;
  82.    
  83.    function getNewCoord(dir, current) {
  84.        
  85.        var speed  = isVunerable() ? 1 : isHidden() ? 4 : 2,
  86.            xSpeed = (dir === LEFT && -speed || dir === RIGHT && speed || 0),
  87.            ySpeed = (dir === DOWN && speed || dir === UP && -speed || 0);
  88.    
  89.        return {
  90.            "x": addBounded(current.x, xSpeed),
  91.            "y": addBounded(current.y, ySpeed)
  92.        };
  93.    };
  94.  
  95.    /* Collision detection(walls) is done when a ghost lands on an
  96.     * exact block, make sure they dont skip over it
  97.     */
  98.    function addBounded(x1, x2) {
  99.        var rem    = x1 % 10,
  100.            result = rem + x2;
  101.        if (rem !== 0 && result > 10) {
  102.            return x1 + (10 - rem);
  103.        } else if(rem > 0 && result < 0) {
  104.            return x1 - rem;
  105.        }
  106.        return x1 + x2;
  107.    };
  108.    
  109.    function isVunerable() {
  110.        return eatable !== null;
  111.    };
  112.    
  113.    function isDangerous() {
  114.        return eaten === null;
  115.    };
  116.  
  117.    function isHidden() {
  118.        return eatable === null && eaten !== null;
  119.    };
  120.    
  121.    function getRandomDirection() {
  122.        var moves = (direction === LEFT || direction === RIGHT)
  123.            ? [UP, DOWN] : [LEFT, RIGHT];
  124.        return moves[Math.floor(Math.random() * 2)];
  125.    };
  126.    
  127.    function reset() {
  128.        eaten = null;
  129.        eatable = null;
  130.        position = {"x": 90, "y": 80};
  131.        direction = getRandomDirection();
  132.        due = getRandomDirection();
  133.    };
  134.    
  135.    function onWholeSquare(x) {
  136.        return x % 10 === 0;
  137.    };
  138.    
  139.    function oppositeDirection(dir) {
  140.        return dir === LEFT && RIGHT ||
  141.            dir === RIGHT && LEFT ||
  142.            dir === UP && DOWN || UP;
  143.    };
  144.  
  145.    function makeEatable() {
  146.        direction = oppositeDirection(direction);
  147.        eatable = game.getTick();
  148.    };
  149.  
  150.    function eat() {
  151.        eatable = null;
  152.        eaten = game.getTick();
  153.    };
  154.  
  155.    function pointToCoord(x) {
  156.        return Math.round(x / 10);
  157.    };
  158.  
  159.    function nextSquare(x, dir) {
  160.        var rem = x % 10;
  161.        if (rem === 0) {
  162.            return x;
  163.        } else if (dir === RIGHT || dir === DOWN) {
  164.            return x + (10 - rem);
  165.        } else {
  166.            return x - rem;
  167.        }
  168.    };
  169.  
  170.    function onGridSquare(pos) {
  171.        return onWholeSquare(pos.y) && onWholeSquare(pos.x);
  172.    };
  173.  
  174.    function secondsAgo(tick) {
  175.        return (game.getTick() - tick) / Pacman.FPS;
  176.    };
  177.  
  178.    function getColour() {
  179.        if (eatable) {
  180.            if (secondsAgo(eatable) > 5) {
  181.                return game.getTick() % 20 > 10 ? "#FFFFFF" : "#0000BB";
  182.            } else {
  183.                return "#0000BB";
  184.            }
  185.        } else if(eaten) {
  186.            return "#222";
  187.        }
  188.        return colour;
  189.    };
  190.  
  191.    function draw(ctx) {
  192.  
  193.        var s    = map.blockSize,
  194.            top  = (position.y/10) * s,
  195.            left = (position.x/10) * s;
  196.    
  197.        if (eatable && secondsAgo(eatable) > 8) {
  198.            eatable = null;
  199.        }
  200.        
  201.        if (eaten && secondsAgo(eaten) > 3) {
  202.            eaten = null;
  203.        }
  204.        
  205.        var tl = left + s;
  206.        var base = top + s - 3;
  207.        var inc = s / 10;
  208.  
  209.        var high = game.getTick() % 10 > 5 ? 3  : -3;
  210.        var low  = game.getTick() % 10 > 5 ? -3 : 3;
  211.  
  212.        ctx.fillStyle = getColour();
  213.        ctx.beginPath();
  214.  
  215.        ctx.moveTo(left, base);
  216.  
  217.        ctx.quadraticCurveTo(left, top, left + (s/2),  top);
  218.        ctx.quadraticCurveTo(left + s, top, left+s,  base);
  219.        
  220.        // Wavy things at the bottom
  221.        ctx.quadraticCurveTo(tl-(inc*1), base+high, tl - (inc * 2),  base);
  222.        ctx.quadraticCurveTo(tl-(inc*3), base+low, tl - (inc * 4),  base);
  223.        ctx.quadraticCurveTo(tl-(inc*5), base+high, tl - (inc * 6),  base);
  224.        ctx.quadraticCurveTo(tl-(inc*7), base+low, tl - (inc * 8),  base);
  225.        ctx.quadraticCurveTo(tl-(inc*9), base+high, tl - (inc * 10), base);
  226.  
  227.        ctx.closePath();
  228.        ctx.fill();
  229.  
  230.        ctx.beginPath();
  231.        ctx.fillStyle = "#FFF";
  232.        ctx.arc(left + 6,top + 6, s / 6, 0, 300, false);
  233.        ctx.arc((left + s) - 6,top + 6, s / 6, 0, 300, false);
  234.        ctx.closePath();
  235.        ctx.fill();
  236.  
  237.        var f = s / 12;
  238.        var off = {};
  239.        off[RIGHT] = [f, 0];
  240.        off[LEFT]  = [-f, 0];
  241.        off[UP]    = [0, -f];
  242.        off[DOWN]  = [0, f];
  243.  
  244.        ctx.beginPath();
  245.        ctx.fillStyle = "#000";
  246.        ctx.arc(left+6+off[direction][0], top+6+off[direction][1],
  247.                s / 15, 0, 300, false);
  248.        ctx.arc((left+s)-6+off[direction][0], top+6+off[direction][1],
  249.                s / 15, 0, 300, false);
  250.        ctx.closePath();
  251.        ctx.fill();
  252.  
  253.    };
  254.  
  255.    function pane(pos) {
  256.  
  257.        if (pos.y === 100 && pos.x >= 190 && direction === RIGHT) {
  258.            return {"y": 100, "x": -10};
  259.        }
  260.        
  261.        if (pos.y === 100 && pos.x <= -10 && direction === LEFT) {
  262.            return position = {"y": 100, "x": 190};
  263.        }
  264.  
  265.        return false;
  266.    };
  267.    
  268.    function move(ctx) {
  269.        
  270.        var oldPos = position,
  271.            onGrid = onGridSquare(position),
  272.            npos   = null;
  273.        
  274.        if (due !== direction) {
  275.            
  276.            npos = getNewCoord(due, position);
  277.            
  278.            if (onGrid &&
  279.                map.isFloorSpace({
  280.                    "y":pointToCoord(nextSquare(npos.y, due)),
  281.                    "x":pointToCoord(nextSquare(npos.x, due))})) {
  282.                direction = due;
  283.            } else {
  284.                npos = null;
  285.            }
  286.        }
  287.        
  288.        if (npos === null) {
  289.            npos = getNewCoord(direction, position);
  290.        }
  291.        
  292.        if (onGrid &&
  293.            map.isWallSpace({
  294.                "y" : pointToCoord(nextSquare(npos.y, direction)),
  295.                "x" : pointToCoord(nextSquare(npos.x, direction))
  296.            })) {
  297.            
  298.            due = getRandomDirection();            
  299.            return move(ctx);
  300.        }
  301.  
  302.        position = npos;        
  303.        
  304.        var tmp = pane(position);
  305.        if (tmp) {
  306.            position = tmp;
  307.        }
  308.        
  309.        due = getRandomDirection();
  310.        
  311.        return {
  312.            "new" : position,
  313.            "old" : oldPos
  314.        };
  315.    };
  316.    
  317.    return {
  318.        "eat"         : eat,
  319.        "isVunerable" : isVunerable,
  320.        "isDangerous" : isDangerous,
  321.        "makeEatable" : makeEatable,
  322.        "reset"       : reset,
  323.        "move"        : move,
  324.        "draw"        : draw
  325.    };
  326. };
  327.  
  328. Pacman.User = function (game, map) {
  329.    
  330.    var position  = null,
  331.        direction = null,
  332.        eaten     = null,
  333.        due       = null,
  334.        lives     = null,
  335.        score     = 5,
  336.        keyMap    = {};
  337.    
  338.    keyMap[KEY.ARROW_LEFT]  = LEFT;
  339.    keyMap[KEY.ARROW_UP]    = UP;
  340.    keyMap[KEY.ARROW_RIGHT] = RIGHT;
  341.    keyMap[KEY.ARROW_DOWN]  = DOWN;
  342.  
  343.    function addScore(nScore) {
  344.        score += nScore;
  345.        if (score >= 10000 && score - nScore < 10000) {
  346.            lives += 1;
  347.        }
  348.    };
  349.  
  350.    function theScore() {
  351.        return score;
  352.    };
  353.  
  354.    function loseLife() {
  355.        lives -= 1;
  356.    };
  357.  
  358.    function getLives() {
  359.        return lives;
  360.    };
  361.  
  362.    function initUser() {
  363.        score = 0;
  364.        lives = 3;
  365.        newLevel();
  366.    }
  367.    
  368.    function newLevel() {
  369.        resetPosition();
  370.        eaten = 0;
  371.    };
  372.    
  373.    function resetPosition() {
  374.        position = {"x": 90, "y": 120};
  375.        direction = LEFT;
  376.        due = LEFT;
  377.    };
  378.    
  379.    function reset() {
  380.        initUser();
  381.        resetPosition();
  382.    };        
  383.    
  384.    function keyDown(e) {
  385.        if (typeof keyMap[e.keyCode] !== "undefined") {
  386.            due = keyMap[e.keyCode];
  387.            e.preventDefault();
  388.            e.stopPropagation();
  389.            return false;
  390.        }
  391.        return true;
  392. };
  393.  
  394.    function getNewCoord(dir, current) {  
  395.        return {
  396.            "x": current.x + (dir === LEFT && -2 || dir === RIGHT && 2 || 0),
  397.            "y": current.y + (dir === DOWN && 2 || dir === UP    && -2 || 0)
  398.        };
  399.    };
  400.  
  401.    function onWholeSquare(x) {
  402.        return x % 10 === 0;
  403.    };
  404.  
  405.    function pointToCoord(x) {
  406.        return Math.round(x/10);
  407.    };
  408.    
  409.    function nextSquare(x, dir) {
  410.        var rem = x % 10;
  411.        if (rem === 0) {
  412.            return x;
  413.        } else if (dir === RIGHT || dir === DOWN) {
  414.            return x + (10 - rem);
  415.        } else {
  416.            return x - rem;
  417.        }
  418.    };
  419.  
  420.    function next(pos, dir) {
  421.        return {
  422.            "y" : pointToCoord(nextSquare(pos.y, dir)),
  423.            "x" : pointToCoord(nextSquare(pos.x, dir)),
  424.        };                              
  425.    };
  426.  
  427.    function onGridSquare(pos) {
  428.        return onWholeSquare(pos.y) && onWholeSquare(pos.x);
  429.    };
  430.  
  431.    function isOnSamePlane(due, dir) {
  432.        return ((due === LEFT || due === RIGHT) &&
  433.                (dir === LEFT || dir === RIGHT)) ||
  434.            ((due === UP || due === DOWN) &&
  435.             (dir === UP || dir === DOWN));
  436.    };
  437.  
  438.    function move(ctx) {
  439.        
  440.        var npos        = null,
  441.            nextWhole   = null,
  442.            oldPosition = position,
  443.            block       = null;
  444.        
  445.        if (due !== direction) {
  446.            npos = getNewCoord(due, position);
  447.            
  448.            if (isOnSamePlane(due, direction) ||
  449.                (onGridSquare(position) &&
  450.                 map.isFloorSpace(next(npos, due)))) {
  451.                direction = due;
  452.            } else {
  453.                npos = null;
  454.            }
  455.        }
  456.  
  457.        if (npos === null) {
  458.            npos = getNewCoord(direction, position);
  459.        }
  460.        
  461.        if (onGridSquare(position) && map.isWallSpace(next(npos, direction))) {
  462.            direction = NONE;
  463.        }
  464.  
  465.        if (direction === NONE) {
  466.            return {"new" : position, "old" : position};
  467.        }
  468.        
  469.        if (npos.y === 100 && npos.x >= 190 && direction === RIGHT) {
  470.            npos = {"y": 100, "x": -10};
  471.        }
  472.        
  473.        if (npos.y === 100 && npos.x <= -12 && direction === LEFT) {
  474.            npos = {"y": 100, "x": 190};
  475.        }
  476.        
  477.        position = npos;        
  478.        nextWhole = next(position, direction);
  479.        
  480.        block = map.block(nextWhole);        
  481.        
  482.        if ((isMidSquare(position.y) || isMidSquare(position.x)) &&
  483.            block === Pacman.BISCUIT || block === Pacman.PILL) {
  484.            
  485.            map.setBlock(nextWhole, Pacman.EMPTY);          
  486.            addScore((block === Pacman.BISCUIT) ? 10 : 50);
  487.            eaten += 1;
  488.            
  489.            if (eaten === 182) {
  490.                game.completedLevel();
  491.            }
  492.            
  493.            if (block === Pacman.PILL) {
  494.                game.eatenPill();
  495.            }
  496.        }  
  497.                
  498.        return {
  499.            "new" : position,
  500.            "old" : oldPosition
  501.        };
  502.    };
  503.  
  504.    function isMidSquare(x) {
  505.        var rem = x % 10;
  506.        return rem > 3 || rem < 7;
  507.    };
  508.  
  509.    function calcAngle(dir, pos) {
  510.        if (dir == RIGHT && (pos.x % 10 < 5)) {
  511.            return {"start":0.25, "end":1.75, "direction": false};
  512.        } else if (dir === DOWN && (pos.y % 10 < 5)) {
  513.            return {"start":0.75, "end":2.25, "direction": false};
  514.        } else if (dir === UP && (pos.y % 10 < 5)) {
  515.            return {"start":1.25, "end":1.75, "direction": true};
  516.        } else if (dir === LEFT && (pos.x % 10 < 5)) {            
  517.            return {"start":0.75, "end":1.25, "direction": true};
  518.        }
  519.        return {"start":0, "end":2, "direction": false};
  520.    };
  521.  
  522.    function drawDead(ctx, amount) {
  523.  
  524.        var size = map.blockSize,
  525.            half = size / 2;
  526.  
  527.        if (amount >= 1) {
  528.            return;
  529.        }
  530.  
  531.        ctx.fillStyle = "#FFFF00";
  532.        ctx.beginPath();        
  533.        ctx.moveTo(((position.x/10) * size) + half,
  534.                   ((position.y/10) * size) + half);
  535.        
  536.        ctx.arc(((position.x/10) * size) + half,
  537.                ((position.y/10) * size) + half,
  538.                half, 0, Math.PI * 2 * amount, true);
  539.        
  540.        ctx.fill();    
  541.    };
  542.  
  543.    function draw(ctx) {
  544.  
  545.        var s     = map.blockSize,
  546.            angle = calcAngle(direction, position);
  547.  
  548.        ctx.fillStyle = "#FFFF00";
  549.  
  550.        ctx.beginPath();        
  551.  
  552.        ctx.moveTo(((position.x/10) * s) + s / 2,
  553.                   ((position.y/10) * s) + s / 2);
  554.        
  555.        ctx.arc(((position.x/10) * s) + s / 2,
  556.                ((position.y/10) * s) + s / 2,
  557.                s / 2, Math.PI * angle.start,
  558.                Math.PI * angle.end, angle.direction);
  559.        
  560.        ctx.fill();    
  561.    };
  562.    
  563.    initUser();
  564.  
  565.    return {
  566.        "draw"          : draw,
  567.        "drawDead"      : drawDead,
  568.        "loseLife"      : loseLife,
  569.        "getLives"      : getLives,
  570.        "score"         : score,
  571.        "addScore"      : addScore,
  572.        "theScore"      : theScore,
  573.        "keyDown"       : keyDown,
  574.        "move"          : move,
  575.        "newLevel"      : newLevel,
  576.        "reset"         : reset,
  577.        "resetPosition" : resetPosition
  578.    };
  579. };
  580.  
  581. Pacman.Map = function (size) {
  582.    
  583.    var height    = null,
  584.        width     = null,
  585.        blockSize = size,
  586.        pillSize  = 0,
  587.        map       = null;
  588.    
  589.    function withinBounds(y, x) {
  590.        return y >= 0 && y < height && x >= 0 && x < width;
  591.    }
  592.    
  593.    function isWall(pos) {
  594.        return withinBounds(pos.y, pos.x) && map[pos.y][pos.x] === Pacman.WALL;
  595.    }
  596.    
  597.    function isFloorSpace(pos) {
  598.        if (!withinBounds(pos.y, pos.x)) {
  599.            return false;
  600.        }
  601.        var peice = map[pos.y][pos.x];
  602.        return peice === Pacman.EMPTY ||
  603.            peice === Pacman.BISCUIT ||
  604.            peice === Pacman.PILL;
  605.    }
  606.    
  607.    function drawWall(ctx) {
  608.  
  609.        var i, j, p, line;
  610.        
  611.        ctx.strokeStyle = "#0000FF";
  612.        ctx.lineWidth   = 5;
  613.        ctx.lineCap     = "round";
  614.        
  615.        for (i = 0; i < Pacman.WALLS.length; i += 1) {
  616.            line = Pacman.WALLS[i];
  617.            ctx.beginPath();
  618.  
  619.            for (j = 0; j < line.length; j += 1) {
  620.  
  621.                p = line[j];
  622.                
  623.                if (p.move) {
  624.                    ctx.moveTo(p.move[0] * blockSize, p.move[1] * blockSize);
  625.                } else if (p.line) {
  626.                    ctx.lineTo(p.line[0] * blockSize, p.line[1] * blockSize);
  627.                } else if (p.curve) {
  628.                    ctx.quadraticCurveTo(p.curve[0] * blockSize,
  629.                                         p.curve[1] * blockSize,
  630.                                         p.curve[2] * blockSize,
  631.                                         p.curve[3] * blockSize);  
  632.                }
  633.            }
  634.            ctx.stroke();
  635.        }
  636.    }
  637.    
  638.    function reset() {      
  639.        map    = Pacman.MAP.clone();
  640.        height = map.length;
  641.        width  = map[0].length;        
  642.    };
  643.  
  644.    function block(pos) {
  645.        return map[pos.y][pos.x];
  646.    };
  647.    
  648.    function setBlock(pos, type) {
  649.        map[pos.y][pos.x] = type;
  650.    };
  651.  
  652.    function drawPills(ctx) {
  653.  
  654.        if (++pillSize > 30) {
  655.            pillSize = 0;
  656.        }
  657.        
  658.        for (i = 0; i < height; i += 1) {
  659.    for (j = 0; j < width; j += 1) {
  660.                if (map[i][j] === Pacman.PILL) {
  661.                    ctx.beginPath();
  662.  
  663.                    ctx.fillStyle = "#000";
  664.            ctx.fillRect((j * blockSize), (i * blockSize),
  665.                                 blockSize, blockSize);
  666.  
  667.                    ctx.fillStyle = "#FFF";
  668.                    ctx.arc((j * blockSize) + blockSize / 2,
  669.                            (i * blockSize) + blockSize / 2,
  670.                            Math.abs(5 - (pillSize/3)),
  671.                            0,
  672.                            Math.PI * 2, false);
  673.                    ctx.fill();
  674.                    ctx.closePath();
  675.                }
  676.    }
  677.    }
  678.    };
  679.    
  680.    function draw(ctx) {
  681.        
  682.        var i, j, size = blockSize;
  683.  
  684.        ctx.fillStyle = "#000";
  685.    ctx.fillRect(0, 0, width * size, height * size);
  686.  
  687.        drawWall(ctx);
  688.        
  689.        for (i = 0; i < height; i += 1) {
  690.    for (j = 0; j < width; j += 1) {
  691.    drawBlock(i, j, ctx);
  692.    }
  693.    }
  694.    };
  695.    
  696.    function drawBlock(y, x, ctx) {
  697.  
  698.        var layout = map[y][x];
  699.  
  700.        if (layout === Pacman.PILL) {
  701.            return;
  702.        }
  703.  
  704.        ctx.beginPath();
  705.        
  706.        if (layout === Pacman.EMPTY || layout === Pacman.BLOCK ||
  707.            layout === Pacman.BISCUIT) {
  708.            
  709.            ctx.fillStyle = "#000";
  710.    ctx.fillRect((x * blockSize), (y * blockSize),
  711.                         blockSize, blockSize);
  712.  
  713.            if (layout === Pacman.BISCUIT) {
  714.                ctx.fillStyle = "#FFF";
  715.        ctx.fillRect((x * blockSize) + (blockSize / 2.5),
  716.                             (y * blockSize) + (blockSize / 2.5),
  717.                             blockSize / 6, blockSize / 6);
  718.        }
  719.        }
  720.        ctx.closePath();
  721.    };
  722.  
  723.    reset();
  724.    
  725.    return {
  726.        "draw"         : draw,
  727.        "drawBlock"    : drawBlock,
  728.        "drawPills"    : drawPills,
  729.        "block"        : block,
  730.        "setBlock"     : setBlock,
  731.        "reset"        : reset,
  732.        "isWallSpace"  : isWall,
  733.        "isFloorSpace" : isFloorSpace,
  734.        "height"       : height,
  735.        "width"        : width,
  736.        "blockSize"    : blockSize
  737.    };
  738. };
  739.  
  740. Pacman.Audio = function(game) {
  741.    
  742.    var files          = [],
  743.        endEvents      = [],
  744.        progressEvents = [],
  745.        playing        = [];
  746.    
  747.    function load(name, path, cb) {
  748.  
  749.        var f = files[name] = document.createElement("audio");
  750.  
  751.        progressEvents[name] = function(event) { progress(event, name, cb); };
  752.        
  753.        f.addEventListener("canplaythrough", progressEvents[name], true);
  754.        f.setAttribute("preload", "true");
  755.        f.setAttribute("autobuffer", "true");
  756.        f.setAttribute("src", path);
  757.        f.pause();        
  758.    };
  759.  
  760.    function progress(event, name, callback) {
  761.        if (event.loaded === event.total && typeof callback === "function") {
  762.            callback();
  763.            files[name].removeEventListener("canplaythrough",
  764.                                            progressEvents[name], true);
  765.        }
  766.    };
  767.  
  768.    function disableSound() {
  769.        for (var i = 0; i < playing.length; i++) {
  770.            files[playing[i]].pause();
  771.            files[playing[i]].currentTime = 0;
  772.        }
  773.        playing = [];
  774.    };
  775.  
  776.    function ended(name) {
  777.  
  778.        var i, tmp = [], found = false;
  779.  
  780.        files[name].removeEventListener("ended", endEvents[name], true);
  781.  
  782.        for (i = 0; i < playing.length; i++) {
  783.            if (!found && playing[i]) {
  784.                found = true;
  785.            } else {
  786.                tmp.push(playing[i]);
  787.            }
  788.        }
  789.        playing = tmp;
  790.    };
  791.  
  792.    function play(name) {
  793.        if (!game.soundDisabled()) {
  794.            endEvents[name] = function() { ended(name); };
  795.            playing.push(name);
  796.            files[name].addEventListener("ended", endEvents[name], true);
  797.            files[name].play();
  798.        }
  799.    };
  800.  
  801.    function pause() {
  802.        for (var i = 0; i < playing.length; i++) {
  803.            files[playing[i]].pause();
  804.        }
  805.    };
  806.    
  807.    function resume() {
  808.        for (var i = 0; i < playing.length; i++) {
  809.            files[playing[i]].play();
  810.        }        
  811.    };
  812.    
  813.    return {
  814.        "disableSound" : disableSound,
  815.        "load"         : load,
  816.        "play"         : play,
  817.        "pause"        : pause,
  818.        "resume"       : resume
  819.    };
  820. };
  821.  
  822. var PACMAN = (function () {
  823.  
  824.    var state        = WAITING,
  825.        audio        = null,
  826.        ghosts       = [],
  827.        ghostSpecs   = ["#00FFDE", "#FF0000", "#FFB8DE", "#FFB847"],
  828.        eatenCount   = 0,
  829.        level        = 0,
  830.        tick         = 0,
  831.        ghostPos, userPos,
  832.        stateChanged = true,
  833.        timerStart   = null,
  834.        lastTime     = 0,
  835.        ctx          = null,
  836.        timer        = null,
  837.        map          = null,
  838.        user         = null,
  839.        stored       = null;
  840.  
  841.    function getTick() {
  842.        return tick;
  843.    };
  844.  
  845.    function drawScore(text, position) {
  846.        ctx.fillStyle = "#FFFFFF";
  847.        ctx.font      = "12px BDCartoonShoutRegular";
  848.        ctx.fillText(text,
  849.                     (position["new"]["x"] / 10) * map.blockSize,
  850.                     ((position["new"]["y"] + 5) / 10) * map.blockSize);
  851.    }
  852.    
  853.    function dialog(text) {
  854.        ctx.fillStyle = "#FFFF00";
  855.        ctx.font      = "18px Calibri";
  856.        var width = ctx.measureText(text).width,
  857.            x     = ((map.width * map.blockSize) - width) / 2;        
  858.        ctx.fillText(text, x, (map.height * 10) + 8);
  859.    }
  860.  
  861.    function soundDisabled() {
  862.        return localStorage["soundDisabled"] === "true";
  863.    };
  864.    
  865.    function startLevel() {        
  866.        user.resetPosition();
  867.        for (var i = 0; i < ghosts.length; i += 1) {
  868.            ghosts[i].reset();
  869.        }
  870.        audio.play("start");
  871.        timerStart = tick;
  872.        setState(COUNTDOWN);
  873.    }    
  874.  
  875.    function startNewGame() {
  876.        setState(WAITING);
  877.        level = 1;
  878.        user.reset();
  879.        map.reset();
  880.        map.draw(ctx);
  881.        startLevel();
  882.    }
  883.  
  884.    function keyDown(e) {
  885.        if (e.keyCode === KEY.N) {
  886.            startNewGame();
  887.        } else if (e.keyCode === KEY.S) {
  888.            audio.disableSound();
  889.            localStorage["soundDisabled"] = !soundDisabled();
  890.        } else if (e.keyCode === KEY.P && state === PAUSE) {
  891.            audio.resume();
  892.            map.draw(ctx);
  893.            setState(stored);
  894.        } else if (e.keyCode === KEY.P) {
  895.            stored = state;
  896.            setState(PAUSE);
  897.            audio.pause();
  898.            map.draw(ctx);
  899.            dialog("Paused");
  900.        } else if (state !== PAUSE) {  
  901.            return user.keyDown(e);
  902.        }
  903.        return true;
  904.    }    
  905.  
  906.    function loseLife() {        
  907.        setState(WAITING);
  908.        user.loseLife();
  909.        if (user.getLives() > 0) {
  910.            startLevel();
  911.        }
  912.    }
  913.  
  914.    function setState(nState) {
  915.        state = nState;
  916.        stateChanged = true;
  917.    };
  918.    
  919.    function collided(user, ghost) {
  920.        return (Math.sqrt(Math.pow(ghost.x - user.x, 2) +
  921.                          Math.pow(ghost.y - user.y, 2))) < 10;
  922.    };
  923.  
  924.    function drawFooter() {
  925.        
  926.        var topLeft  = (map.height * map.blockSize),
  927.            textBase = topLeft + 17;
  928.        
  929.        ctx.fillStyle = "#000000";
  930.        ctx.fillRect(0, topLeft, (map.width * map.blockSize), 30);
  931.        
  932.        ctx.fillStyle = "#FFFF00";
  933.  
  934.        for (var i = 0, len = user.getLives(); i < len; i++) {
  935.            ctx.fillStyle = "#FFFF00";
  936.            ctx.beginPath();
  937.            ctx.moveTo(150 + (25 * i) + map.blockSize / 2,
  938.                       (topLeft+1) + map.blockSize / 2);
  939.            
  940.            ctx.arc(150 + (25 * i) + map.blockSize / 2,
  941.                    (topLeft+1) + map.blockSize / 2,
  942.                    map.blockSize / 2, Math.PI * 0.25, Math.PI * 1.75, false);
  943.            ctx.fill();
  944.        }
  945.  
  946.        ctx.fillStyle = !soundDisabled() ? "#00FF00" : "#FF0000";
  947.        ctx.font = "bold 16px sans-serif";
  948.        //ctx.fillText("♪", 10, textBase);
  949.        ctx.fillText("s", 10, textBase);
  950.  
  951.        ctx.fillStyle = "#FFFF00";
  952.        ctx.font      = "14px Calibri";
  953.        ctx.fillText("Score: " + user.theScore(), 30, textBase);
  954.        ctx.fillText("Level: " + level, 260, textBase);
  955.    }
  956.  
  957.    function redrawBlock(pos) {
  958.        map.drawBlock(Math.floor(pos.y/10), Math.floor(pos.x/10), ctx);
  959.        map.drawBlock(Math.ceil(pos.y/10), Math.ceil(pos.x/10), ctx);
  960.    }
  961.  
  962.    function mainDraw() {
  963.  
  964.        var diff, u, i, len, nScore;
  965.        
  966.        ghostPos = [];
  967.  
  968.        for (i = 0, len = ghosts.length; i < len; i += 1) {
  969.            ghostPos.push(ghosts[i].move(ctx));
  970.        }
  971.        u = user.move(ctx);
  972.        
  973.        for (i = 0, len = ghosts.length; i < len; i += 1) {
  974.            redrawBlock(ghostPos[i].old);
  975.        }
  976.        redrawBlock(u.old);
  977.        
  978.        for (i = 0, len = ghosts.length; i < len; i += 1) {
  979.            ghosts[i].draw(ctx);
  980.        }                    
  981.        user.draw(ctx);
  982.        
  983.        userPos = u["new"];
  984.        
  985.        for (i = 0, len = ghosts.length; i < len; i += 1) {
  986.            if (collided(userPos, ghostPos[i]["new"])) {
  987.                if (ghosts[i].isVunerable()) {
  988.                    audio.play("eatghost");
  989.                    ghosts[i].eat();
  990.                    eatenCount += 1;
  991.                    nScore = eatenCount * 50;
  992.                    drawScore(nScore, ghostPos[i]);
  993.                    user.addScore(nScore);                    
  994.                    setState(EATEN_PAUSE);
  995.                    timerStart = tick;
  996.                } else if (ghosts[i].isDangerous()) {
  997.                    audio.play("die");
  998.                    setState(DYING);
  999.                    timerStart = tick;
  1000.                }
  1001.            }
  1002.        }                            
  1003.    };
  1004.  
  1005.    function mainLoop() {
  1006.  
  1007.        var diff;
  1008.  
  1009.        if (state !== PAUSE) {
  1010.            ++tick;
  1011.        }
  1012.  
  1013.        map.drawPills(ctx);
  1014.  
  1015.        if (state === PLAYING) {
  1016.            mainDraw();
  1017.        } else if (state === WAITING && stateChanged) {            
  1018.            stateChanged = false;
  1019.            map.draw(ctx);
  1020.            dialog("Press N to start a New game");            
  1021.        } else if (state === EATEN_PAUSE &&
  1022.                   (tick - timerStart) > (Pacman.FPS / 3)) {
  1023.            map.draw(ctx);
  1024.            setState(PLAYING);
  1025.        } else if (state === DYING) {
  1026.            if (tick - timerStart > (Pacman.FPS * 2)) {
  1027.                loseLife();
  1028.            } else {
  1029.                redrawBlock(userPos);
  1030.                for (i = 0, len = ghosts.length; i < len; i += 1) {
  1031.                    redrawBlock(ghostPos[i].old);
  1032.                    ghostPos.push(ghosts[i].draw(ctx));
  1033.                }                                  
  1034.                user.drawDead(ctx, (tick - timerStart) / (Pacman.FPS * 2));
  1035.            }
  1036.        } else if (state === COUNTDOWN) {
  1037.            
  1038.            diff = 5 + Math.floor((timerStart - tick) / Pacman.FPS);
  1039.            
  1040.            if (diff === 0) {
  1041.                map.draw(ctx);
  1042.                setState(PLAYING);
  1043.            } else {
  1044.                if (diff !== lastTime) {
  1045.                    lastTime = diff;
  1046.                    map.draw(ctx);
  1047.                    dialog("Starting in: " + diff);
  1048.                }
  1049.            }
  1050.        }
  1051.  
  1052.        drawFooter();
  1053.    }
  1054.  
  1055.    function eatenPill() {
  1056.        audio.play("eatpill");
  1057.        timerStart = tick;
  1058.        eatenCount = 0;
  1059.        for (i = 0; i < ghosts.length; i += 1) {
  1060.            ghosts[i].makeEatable(ctx);
  1061.        }        
  1062.    };
  1063.    
  1064.    function completedLevel() {
  1065.        setState(WAITING);
  1066.        level += 1;
  1067.        map.reset();
  1068.        user.newLevel();
  1069.        startLevel();
  1070.    };
  1071.  
  1072.    function keyPress(e) {
  1073.        if (state !== WAITING && state !== PAUSE) {
  1074.            e.preventDefault();
  1075.            e.stopPropagation();
  1076.        }
  1077.    };
  1078.    
  1079.    function init(wrapper, root) {
  1080.        
  1081.        var i, len, ghost,
  1082.            blockSize = wrapper.offsetWidth / 19,
  1083.            canvas    = document.createElement("canvas");
  1084.        
  1085.        canvas.setAttribute("width", (blockSize * 19) + "px");
  1086.        canvas.setAttribute("height", (blockSize * 22) + 30 + "px");
  1087.  
  1088.        wrapper.appendChild(canvas);
  1089.  
  1090.        ctx  = canvas.getContext('2d');
  1091.  
  1092.        audio = new Pacman.Audio({"soundDisabled":soundDisabled});
  1093.        map   = new Pacman.Map(blockSize);
  1094.        user  = new Pacman.User({
  1095.            "completedLevel" : completedLevel,
  1096.            "eatenPill"      : eatenPill
  1097.        }, map);
  1098.  
  1099.        for (i = 0, len = ghostSpecs.length; i < len; i += 1) {
  1100.            ghost = new Pacman.Ghost({"getTick":getTick}, map, ghostSpecs[i]);
  1101.            ghosts.push(ghost);
  1102.        }
  1103.        
  1104.        map.draw(ctx);
  1105.        dialog("Loading ...");
  1106.  
  1107.        var extension = Modernizr.audio.ogg ? 'ogg' : 'mp3';
  1108.  
  1109.        var audio_files = [
  1110.            ["start", root + "audio/opening_song." + extension],
  1111.            ["die", root + "audio/die." + extension],
  1112.            ["eatghost", root + "audio/eatghost." + extension],
  1113.            ["eatpill", root + "audio/eatpill." + extension],
  1114.            ["eating", root + "audio/eating.short." + extension],
  1115.            ["eating2", root + "audio/eating.short." + extension]
  1116.        ];
  1117.  
  1118.        load(audio_files, function() { loaded(); });
  1119.    };
  1120.  
  1121.    function load(arr, callback) {
  1122.        
  1123.        if (arr.length === 0) {
  1124.            callback();
  1125.        } else {
  1126.            var x = arr.pop();
  1127.            audio.load(x[0], x[1], function() { load(arr, callback); });
  1128.        }
  1129.    };
  1130.        
  1131.    function loaded() {
  1132.  
  1133.        dialog("Press N to Start");
  1134.        
  1135.        document.addEventListener("keydown", keyDown, true);
  1136.        document.addEventListener("keypress", keyPress, true);
  1137.        
  1138.        timer = window.setInterval(mainLoop, 1000 / Pacman.FPS);
  1139.    };
  1140.    
  1141.    return {
  1142.        "init" : init
  1143.    };
  1144.    
  1145. }());
  1146.  
  1147. /* Human readable keyCode index */
  1148. var KEY = {'BACKSPACE': 8, 'TAB': 9, 'NUM_PAD_CLEAR': 12, 'ENTER': 13, 'SHIFT': 16, 'CTRL': 17, 'ALT': 18, 'PAUSE': 19, 'CAPS_LOCK': 20, 'ESCAPE': 27, 'SPACEBAR': 32, 'PAGE_UP': 33, 'PAGE_DOWN': 34, 'END': 35, 'HOME': 36, 'ARROW_LEFT': 37, 'ARROW_UP': 38, 'ARROW_RIGHT': 39, 'ARROW_DOWN': 40, 'PRINT_SCREEN': 44, 'INSERT': 45, 'DELETE': 46, 'SEMICOLON': 59, 'WINDOWS_LEFT': 91, 'WINDOWS_RIGHT': 92, 'SELECT': 93, 'NUM_PAD_ASTERISK': 106, 'NUM_PAD_PLUS_SIGN': 107, 'NUM_PAD_HYPHEN-MINUS': 109, 'NUM_PAD_FULL_STOP': 110, 'NUM_PAD_SOLIDUS': 111, 'NUM_LOCK': 144, 'SCROLL_LOCK': 145, 'SEMICOLON': 186, 'EQUALS_SIGN': 187, 'COMMA': 188, 'HYPHEN-MINUS': 189, 'FULL_STOP': 190, 'SOLIDUS': 191, 'GRAVE_ACCENT': 192, 'LEFT_SQUARE_BRACKET': 219, 'REVERSE_SOLIDUS': 220, 'RIGHT_SQUARE_BRACKET': 221, 'APOSTROPHE': 222};
  1149.  
  1150. (function () {
  1151. /* 0 - 9 */
  1152. for (var i = 48; i <= 57; i++) {
  1153.        KEY['' + (i - 48)] = i;
  1154. }
  1155. /* A - Z */
  1156. for (i = 65; i <= 90; i++) {
  1157.        KEY['' + String.fromCharCode(i)] = i;
  1158. }
  1159. /* NUM_PAD_0 - NUM_PAD_9 */
  1160. for (i = 96; i <= 105; i++) {
  1161.        KEY['NUM_PAD_' + (i - 96)] = i;
  1162. }
  1163. /* F1 - F12 */
  1164. for (i = 112; i <= 123; i++) {
  1165.        KEY['F' + (i - 112 + 1)] = i;
  1166. }
  1167. })();
  1168.  
  1169. Pacman.WALL    = 0;
  1170. Pacman.BISCUIT = 1;
  1171. Pacman.EMPTY   = 2;
  1172. Pacman.BLOCK   = 3;
  1173. Pacman.PILL    = 4;
  1174.  
  1175. Pacman.MAP = [
  1176.    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  1177. [0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
  1178. [0, 4, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 4, 0],
  1179. [0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0],
  1180. [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
  1181. [0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0],
  1182. [0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
  1183. [0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0],
  1184. [2, 2, 2, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 2, 2, 2],
  1185. [0, 0, 0, 0, 1, 0, 1, 0, 0, 3, 0, 0, 1, 0, 1, 0, 0, 0, 0],
  1186. [2, 2, 2, 2, 1, 1, 1, 0, 3, 3, 3, 0, 1, 1, 1, 2, 2, 2, 2],
  1187. [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
  1188. [2, 2, 2, 0, 1, 0, 1, 1, 1, 2, 1, 1, 1, 0, 1, 0, 2, 2, 2],
  1189. [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
  1190. [0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
  1191. [0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0],
  1192. [0, 4, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 4, 0],
  1193. [0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0],
  1194. [0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
  1195. [0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0],
  1196. [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
  1197. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  1198. ];
  1199.  
  1200. Pacman.WALLS = [
  1201.    
  1202.    [{"move": [0, 9.5]}, {"line": [3, 9.5]},
  1203.     {"curve": [3.5, 9.5, 3.5, 9]}, {"line": [3.5, 8]},
  1204.     {"curve": [3.5, 7.5, 3, 7.5]}, {"line": [1, 7.5]},
  1205.     {"curve": [0.5, 7.5, 0.5, 7]}, {"line": [0.5, 1]},
  1206.     {"curve": [0.5, 0.5, 1, 0.5]}, {"line": [9, 0.5]},
  1207.     {"curve": [9.5, 0.5, 9.5, 1]}, {"line": [9.5, 3.5]}],
  1208.  
  1209.    [{"move": [9.5, 1]},
  1210.     {"curve": [9.5, 0.5, 10, 0.5]}, {"line": [18, 0.5]},
  1211.     {"curve": [18.5, 0.5, 18.5, 1]}, {"line": [18.5, 7]},
  1212.     {"curve": [18.5, 7.5, 18, 7.5]}, {"line": [16, 7.5]},
  1213.     {"curve": [15.5, 7.5, 15.5, 8]}, {"line": [15.5, 9]},
  1214.     {"curve": [15.5, 9.5, 16, 9.5]}, {"line": [19, 9.5]}],
  1215.  
  1216.    [{"move": [2.5, 5.5]}, {"line": [3.5, 5.5]}],
  1217.  
  1218.    [{"move": [3, 2.5]},
  1219.     {"curve": [3.5, 2.5, 3.5, 3]},
  1220.     {"curve": [3.5, 3.5, 3, 3.5]},
  1221.     {"curve": [2.5, 3.5, 2.5, 3]},
  1222.     {"curve": [2.5, 2.5, 3, 2.5]}],
  1223.  
  1224.    [{"move": [15.5, 5.5]}, {"line": [16.5, 5.5]}],
  1225.  
  1226.    [{"move": [16, 2.5]}, {"curve": [16.5, 2.5, 16.5, 3]},
  1227.     {"curve": [16.5, 3.5, 16, 3.5]}, {"curve": [15.5, 3.5, 15.5, 3]},
  1228.     {"curve": [15.5, 2.5, 16, 2.5]}],
  1229.  
  1230.    [{"move": [6, 2.5]}, {"line": [7, 2.5]}, {"curve": [7.5, 2.5, 7.5, 3]},
  1231.     {"curve": [7.5, 3.5, 7, 3.5]}, {"line": [6, 3.5]},
  1232.     {"curve": [5.5, 3.5, 5.5, 3]}, {"curve": [5.5, 2.5, 6, 2.5]}],
  1233.  
  1234.    [{"move": [12, 2.5]}, {"line": [13, 2.5]}, {"curve": [13.5, 2.5, 13.5, 3]},
  1235.     {"curve": [13.5, 3.5, 13, 3.5]}, {"line": [12, 3.5]},
  1236.     {"curve": [11.5, 3.5, 11.5, 3]}, {"curve": [11.5, 2.5, 12, 2.5]}],
  1237.  
  1238.    [{"move": [7.5, 5.5]}, {"line": [9, 5.5]}, {"curve": [9.5, 5.5, 9.5, 6]},
  1239.     {"line": [9.5, 7.5]}],
  1240.    [{"move": [9.5, 6]}, {"curve": [9.5, 5.5, 10.5, 5.5]},
  1241.     {"line": [11.5, 5.5]}],
  1242.  
  1243.  
  1244.    [{"move": [5.5, 5.5]}, {"line": [5.5, 7]}, {"curve": [5.5, 7.5, 6, 7.5]},
  1245.     {"line": [7.5, 7.5]}],
  1246.    [{"move": [6, 7.5]}, {"curve": [5.5, 7.5, 5.5, 8]}, {"line": [5.5, 9.5]}],
  1247.  
  1248.    [{"move": [13.5, 5.5]}, {"line": [13.5, 7]},
  1249.     {"curve": [13.5, 7.5, 13, 7.5]}, {"line": [11.5, 7.5]}],
  1250.    [{"move": [13, 7.5]}, {"curve": [13.5, 7.5, 13.5, 8]},
  1251.     {"line": [13.5, 9.5]}],
  1252.  
  1253.    [{"move": [0, 11.5]}, {"line": [3, 11.5]}, {"curve": [3.5, 11.5, 3.5, 12]},
  1254.     {"line": [3.5, 13]}, {"curve": [3.5, 13.5, 3, 13.5]}, {"line": [1, 13.5]},
  1255.     {"curve": [0.5, 13.5, 0.5, 14]}, {"line": [0.5, 17]},
  1256.     {"curve": [0.5, 17.5, 1, 17.5]}, {"line": [1.5, 17.5]}],
  1257.    [{"move": [1, 17.5]}, {"curve": [0.5, 17.5, 0.5, 18]}, {"line": [0.5, 21]},
  1258.     {"curve": [0.5, 21.5, 1, 21.5]}, {"line": [18, 21.5]},
  1259.     {"curve": [18.5, 21.5, 18.5, 21]}, {"line": [18.5, 18]},
  1260.     {"curve": [18.5, 17.5, 18, 17.5]}, {"line": [17.5, 17.5]}],
  1261.    [{"move": [18, 17.5]}, {"curve": [18.5, 17.5, 18.5, 17]},
  1262.     {"line": [18.5, 14]}, {"curve": [18.5, 13.5, 18, 13.5]},
  1263.     {"line": [16, 13.5]}, {"curve": [15.5, 13.5, 15.5, 13]},
  1264.     {"line": [15.5, 12]}, {"curve": [15.5, 11.5, 16, 11.5]},
  1265.     {"line": [19, 11.5]}],
  1266.  
  1267.    [{"move": [5.5, 11.5]}, {"line": [5.5, 13.5]}],
  1268.    [{"move": [13.5, 11.5]}, {"line": [13.5, 13.5]}],
  1269.  
  1270.    [{"move": [2.5, 15.5]}, {"line": [3, 15.5]},
  1271.     {"curve": [3.5, 15.5, 3.5, 16]}, {"line": [3.5, 17.5]}],
  1272.    [{"move": [16.5, 15.5]}, {"line": [16, 15.5]},
  1273.     {"curve": [15.5, 15.5, 15.5, 16]}, {"line": [15.5, 17.5]}],
  1274.  
  1275.    [{"move": [5.5, 15.5]}, {"line": [7.5, 15.5]}],
  1276.    [{"move": [11.5, 15.5]}, {"line": [13.5, 15.5]}],
  1277.    
  1278.    [{"move": [2.5, 19.5]}, {"line": [5, 19.5]},
  1279.     {"curve": [5.5, 19.5, 5.5, 19]}, {"line": [5.5, 17.5]}],
  1280.    [{"move": [5.5, 19]}, {"curve": [5.5, 19.5, 6, 19.5]},
  1281.     {"line": [7.5, 19.5]}],
  1282.  
  1283.    [{"move": [11.5, 19.5]}, {"line": [13, 19.5]},
  1284.     {"curve": [13.5, 19.5, 13.5, 19]}, {"line": [13.5, 17.5]}],
  1285.    [{"move": [13.5, 19]}, {"curve": [13.5, 19.5, 14, 19.5]},
  1286.     {"line": [16.5, 19.5]}],
  1287.  
  1288.    [{"move": [7.5, 13.5]}, {"line": [9, 13.5]},
  1289.     {"curve": [9.5, 13.5, 9.5, 14]}, {"line": [9.5, 15.5]}],
  1290.    [{"move": [9.5, 14]}, {"curve": [9.5, 13.5, 10, 13.5]},
  1291.     {"line": [11.5, 13.5]}],
  1292.  
  1293.    [{"move": [7.5, 17.5]}, {"line": [9, 17.5]},
  1294.     {"curve": [9.5, 17.5, 9.5, 18]}, {"line": [9.5, 19.5]}],
  1295.    [{"move": [9.5, 18]}, {"curve": [9.5, 17.5, 10, 17.5]},
  1296.     {"line": [11.5, 17.5]}],
  1297.  
  1298.    [{"move": [8.5, 9.5]}, {"line": [8, 9.5]}, {"curve": [7.5, 9.5, 7.5, 10]},
  1299.     {"line": [7.5, 11]}, {"curve": [7.5, 11.5, 8, 11.5]},
  1300.     {"line": [11, 11.5]}, {"curve": [11.5, 11.5, 11.5, 11]},
  1301.     {"line": [11.5, 10]}, {"curve": [11.5, 9.5, 11, 9.5]},
  1302.     {"line": [10.5, 9.5]}]
  1303. ];
  1304.  
  1305. Object.prototype.clone = function () {
  1306.    var i, newObj = (this instanceof Array) ? [] : {};
  1307.    for (i in this) {
  1308.        if (i === 'clone') {
  1309.            continue;
  1310.        }
  1311.        if (this[i] && typeof this[i] === "object") {
  1312.            newObj[i] = this[i].clone();
  1313.        } else {
  1314.            newObj[i] = this[i];
  1315.        }
  1316.    }
  1317.    return newObj;
  1318. };
  1319.  
  1320. $(function(){
  1321.  var el = document.getElementById("pacman");
  1322.  
  1323.  if (Modernizr.canvas && Modernizr.localstorage &&
  1324.      Modernizr.audio && (Modernizr.audio.ogg || Modernizr.audio.mp3)) {
  1325.    window.setTimeout(function () { PACMAN.init(el, "https://raw.githubusercontent.com/daleharvey/pacman/master/"); }, 0);
  1326.  } else {
  1327.    el.innerHTML = "Sorry, needs a decent browser<br /><small>" +
  1328.      "(firefox 3.6+, Chrome 4+, Opera 10+ and Safari 4+)</small>";
  1329.  }
  1330. });
  1331.  
  1332.  
  1333. </script>
  1334. <script defer src="https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015" integrity="sha512-ZpsOmlRQV6y907TI0dKBHq9Md29nnaEIPlkf84rnaERnq6zvWvPUqr2ft8M1aS28oN72PdrCzSjY4U6VaAw1EQ==" data-cf-beacon='{"version":"2024.11.0","token":"05f52152ee4e41f2a77cd618d6a931a1","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
  1335. </body>
  1336. </html>
Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda