<body>

    <!-- map and options -->
    <section id="main_section">

        <!-- map -->
        <div id="grid_map_container">
            <p id="grid_map"></p>
        </div>

        <!-- text and options -->
        <div id="text-option" onmouseover="reset_mouse()">
            <h2>Optimal Walling</h2>

            <p>Optimal Walling is a Quality of Life suggestion for <a href="https://www.ageofempires.com/games/aoeiide/">AoE2 DE</a> from <a href="https://www.ageofempires.com/mods/details/15625/">Age of Salamanders</a>.</p>

            <p>When building a wall in the current implementation, the game only uses horizontal and vertical lines, except if the wall can be built with a single diagonal line.</p>

            <p>This results in walls far from the ideal straight line and costing too much wood/stone.</p>

            <!-- choose the action type -->
            <div id=radio-tile>

                <h3>Fill the map tiles with...</h3>

                <div class="radio-paint">
                    <input type="radio" id="radio-grass" name="radio-tile" value="grass">
                    <label for="radio-grass">Grass</label>

                    <input type="radio" id="radio-forest" name="radio-tile" value="forest">
                    <label for="radio-forest">Forest</label>

                    <input type="radio" id="radio-building" name="radio-tile" value="building">
                    <label for="radio-building">Building</label>

                    <input type="radio" id="radio-water" name="radio-tile" value="water">
                    <label for="radio-water">Water</label>

                    <!-- clear of the full map -->
                    <button id="clear_map" onclick="clear_map()">Clear Map</button>

                    <!-- reset of the full map -->
                    <button id="reset_map" onclick="reset_map()">Reset Map</button>
                </div>

                <p>Click (left mouse button) a tile or draw a rectangle.</p>

                <div id="optimal-walling">
                    <h3>Test Optimal Walling</h3>

                    <div class="radio-paint">
                        <input type="radio" id="radio-wall" name="radio-tile" value="wall" checked>
                        <label for="radio-wall">Wall</label>
                    </div>

                    <div>
                        <input type="checkbox" id="game_implement" name="game_implement" checked>
                        <label for="scales" id="game_implement_label">Show game current implementation</label>
                    </div>
                </div>

                <p>Click (left mouse button) on a tile and release it on another tile, like what is currently done in the game.</p>

                <p>While maintaining the left button pressed, click on the right button (or use the mouse wheel) to cycle between 4 configurations.</p>
            </div>
        </div>
    </section>
</body>
/* define colors */

:root {
    --grass-color: rgb(113, 219, 7);
    --forest-color: rgb(63, 99, 28);
    --building-color: rgb(151, 58, 1);
    --water-color: rgb(62, 138, 252);
    --wall-color: rgb(150, 150, 150);
    --old-wall-color: rgb(255, 230, 0);
    --both-wall-color: rgb(184, 176, 100);
    --button-color: rgb(230, 230, 230);
    --text-background-color: rgb(255, 255, 204);
}


/* main background*/

body {
    background-image: url("http://nvandernoot.gitlab.io/docs/pictures/aoe2/codepen/wood_pattern.jpg");
    background-repeat: no-repeat;
    background-size: cover;
    color: black;
    font-size: 120%;
}


/* grid, text and options */

#main_section {
    display: flex;
    flex-direction: row;
}


/* grid margins */

#grid_map {
    margin-left: 20px;
    margin-right: 20px;
}


/* text & option margins */

#text-option {
    padding-left: 20px;
    padding-right: 20px;
    max-width: 700px;
    border-radius: 10px;
    border-style: solid;
    background-color: var(--text-background-color);
}


/* href links */

a:hover,
a:visited,
a:link,
a:active {
    color: black;
    font-weight: bold;
    text-decoration: none;
}


/* size of the grid */

#grid-container {
    display: grid;
    /* 20 x 15 map */
    grid-template-columns: 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px;
    grid-template-rows: 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px;
    background-color: #000000;
    padding: 5px;
}


/* radio buttons for painting */

.radio-paint {
    display: flex;
    flex-direction: row;
}

.radio-paint input[type="radio"] {
    opacity: 0;
    position: fixed;
    width: 0;
}

.radio-paint label {
    padding: 10px 10px;
    border-radius: 4px;
    margin-left: 10px;
    margin-right: 10px;
    border: 2px solid;
    height: 20px;
}

.radio-paint label[for="radio-grass"] {
    border-color: var(--grass-color);
}

.radio-paint label[for="radio-forest"] {
    border-color: var(--forest-color);
}

.radio-paint label[for="radio-building"] {
    border-color: var(--building-color);
}

.radio-paint label[for="radio-water"] {
    border-color: var(--water-color);
}

.radio-paint label[for="radio-wall"] {
    border-color: var(--wall-color);
    margin-left: 30px;
}

.radio-paint input[id="radio-grass"]:checked+label {
    background-color: var(--grass-color);
    border-color: black;
}

.radio-paint input[id="radio-forest"]:checked+label {
    background-color: var(--forest-color);
    border-color: black;
}

.radio-paint input[id="radio-building"]:checked+label {
    background-color: var(--building-color);
    border-color: black;
}

.radio-paint input[id="radio-water"]:checked+label {
    background-color: var(--water-color);
    border-color: black;
}

.radio-paint input[id="radio-wall"]:checked+label {
    background-color: var(--wall-color);
    border-color: black;
}


/* map clear and reset */

#clear_map,
#reset_map {
    padding: 5px 5px;
    border-radius: 4px;
    margin-left: 10px;
    margin-right: 10px;
    border: 2px solid;
    background-color: var(--button-color);
    font-size: 17px;
}


/* Optimal Walling test */

#optimal-walling {
    display: flex;
    flex-direction: row;
    align-items: center;
}


/* Checkbox to see the game current implementation */

#game_implement {
    margin-left: 50px;
}

#game_implement_label {
    margin-left: 10px;
    padding: 10px;
    border-style: solid;
    border-style: dashed;
    border-radius: 4px;
    border-color: var(--old-wall-color);
}

input[type=checkbox] {
    transform: scale(1.5);
}


/* tiles colors */

.grass-tile {
    background-color: var(--grass-color);
    border: 1px solid black;
}

.forest-tile {
    background-color: var(--forest-color);
    border: 1px solid black;
}

.building-tile {
    background-color: var(--building-color);
    border: 1px solid black;
}

.water-tile {
    background-color: var(--water-color);
    border: 1px solid black;
}

.wall-tile {
    background-color: var(--wall-color);
    border: 1px solid black;
}

.old-wall-tile {
    background-color: var(--old-wall-color);
    border: 1px solid black;
}

.both-wall-tile {
    background-color: var(--both-wall-color);
    border: 1px solid black;
}
// tile possible states
const tile = {
    GRASS: 'grass',
    FOREST: 'forest',
    BUILDING: 'building',
    WATER: 'water',
    WALL: 'wall',
    OLD_WALL: 'old-wall',
    BOTH_WALL: 'both-wall',
};

// wall lines description
const wall_line = {
    NONE: 'none',
    SINGLE: 'single',
    HORIZONTAL: 'horizontal',
    VERTICAL: 'vertical',
    DIAGONAL: 'diagonal',
};

// choice of the type of wall
const wall_choice = {
    DIAGONAL_1: 'diagonal_1',
    DIAGONAL_2: 'diagonal_2',
    NO_DIAGONAL_1: 'no_diagonal_1',
    NO_DIAGONAL_2: 'no_diagonal_2',
};

// Computation related to the grid
class GridComputation {

    // constructor receiving the size of the grid
    constructor(rows_count, columns_count) {
        // size of the grid
        this.rows_count = rows_count; // number of rows (height)
        this.columns_count = columns_count; // number of columns (width)

        // mouse state
        this.mouse_x = -1; // X position on the grid
        this.mouse_y = -1; // Y position on the grid
        this.mouse_left_pressed = false; // left button currently pressed
        this.mouse_right_pressed = false; // right button currently pressed
        this.last_mouse_left_pressed = false; // last state of 'mouse_left_pressed' during update
        this.last_mouse_right_pressed = false; // last state of 'mouse_right_pressed' during update

        // wall straight lines end points
        this.wall_xa = -1; // X position of the first end point
        this.wall_ya = -1; // Y position of the first end point
        this.wall_xb = -1; // X position of the last end point
        this.wall_yb = -1; // Y position of the last end point
        this.wall_xc = -1; // X position of the potential middle point
        this.wall_yc = -1; // Y position of the potential middle point

        // area tiles painting
        this.paint_xa = -1; // X position of the first tile being clicked
        this.paint_ya = -1; // Y position of the first tile being clicked
        this.paint_xb = -1; // X position of the tile being currently hovered
        this.paint_yb = -1; // Y position of the tile being currently hovered

        // wall two lines description
        this.wall_line_1 = wall_line.NONE;
        this.wall_line_2 = wall_line.NONE;

        // choosing the type of walling
        this.wall_choice = wall_choice.DIAGONAL_1;

        // wall being built (true) or not (false)
        this.building = false;

        // tile painting activated (true) or not (false)
        this.painting = false;

        // tile action type (painting tile choice or wall building)
        this.tile_action = tile.WALL;

        // map array creation and initialization
        this.map_array = this.initialize_map_array();
        this.initial_map();
    }

    // reset the mouse position (-1 for outside the grid)
    reset_mouse() {
        this.mouse_x = -1;
        this.mouse_y = -1;
    }

    // check mouse buttons
    check_mouse_buttons() {
        // left button
        if (this.mouse_left_pressed != this.last_mouse_left_pressed) // new state
        {
            if (this.mouse_left_pressed) // start pressing
            {
                this.wall_choice = wall_choice.DIAGONAL_1; // reset to first configuration
            }
            this.last_mouse_left_pressed = this.mouse_left_pressed;
        }

        // right button
        if (this.mouse_right_pressed != this.last_mouse_right_pressed) // new state
        {
            if (!this.mouse_right_pressed) // stop pressing
            {
                this.update_wall_choice(); // change wall choice
            }
            this.last_mouse_right_pressed = this.mouse_right_pressed;
        }
    }

    // read tile options
    read_tile_option() {
        var radios = document.getElementsByName('radio-tile');

        for (var i = 0, length = radios.length; i < length; i++) {
            if (radios[i].checked) {
                switch (radios[i].value) {
                    case "grass":
                        this.tile_action = tile.GRASS;
                        break;

                    case "forest":
                        this.tile_action = tile.FOREST;
                        break;

                    case "building":
                        this.tile_action = tile.BUILDING;
                        break;

                    case "water":
                        this.tile_action = tile.WATER;
                        break;

                    case "wall":
                        this.tile_action = tile.WALL;
                        break;

                    default:
                        break;
                }
                break; // radio button found
            }
        }
    }

    // initialize (and return) the map array
    initialize_map_array() {
        let map = new Array(this.rows_count);

        for (let i = 0; i < this.rows_count; i++) {
            map[i] = new Array(this.columns_count);
            for (let j = 0; j < this.columns_count; j++) {
                map[i][j] = tile.GRASS; // initialize by default with grass
            }
        }
        return map;
    }

    // clear the map with only grass
    clear_map() {
        for (let i = 0; i < this.rows_count; i++) {
            for (let j = 0; j < this.columns_count; j++) {
                this.map_array[i][j] = tile.GRASS;
            }
        }
    }

    // fill area with same tiles
    area_tiles(x0, x1, y0, y1, type) {
        for (let y = y0; y <= y1; y++) {
            for (let x = x0; x <= x1; x++) {
                this.map_array[y][x] = type;
            }
        }
    }

    // fill horizontal line with same tiles
    horizontal_tiles(x0, x1, y, type) {
        for (let x = x0; x <= x1; x++) {
            this.map_array[y][x] = type;
        }
    }

    // fill vertical line with same tiles
    vertical_tiles(x, y0, y1, type) {
        for (let y = y0; y <= y1; y++) {
            this.map_array[y][x] = type;
        }
    }

    // initial map landmarks
    initial_map() {

        // start by clearing any element of the map
        this.clear_map();

        // buildings
        this.area_tiles(7, 9, 6, 8, tile.BUILDING);
        this.area_tiles(11, 12, 4, 5, tile.BUILDING);

        // forests
        this.area_tiles(0, 2, 0, 1, tile.FOREST);
        this.horizontal_tiles(0, 1, 2, tile.FOREST);
        this.area_tiles(0, 1, 11, 14, tile.FOREST);
        this.vertical_tiles(2, 12, 14, tile.FOREST);
        this.horizontal_tiles(3, 5, 14, tile.FOREST);
        this.horizontal_tiles(15, 19, 0, tile.FOREST);
        this.area_tiles(17, 19, 1, 3, tile.FOREST);

        // water
        this.area_tiles(17, 19, 11, 14, tile.WATER);
        this.horizontal_tiles(17, 18, 10, tile.WATER);
        this.vertical_tiles(16, 12, 14, tile.WATER);
        this.vertical_tiles(15, 13, 14, tile.WATER);
        this.horizontal_tiles(13, 14, 14, tile.WATER);

        // walls
        this.horizontal_tiles(5, 14, 0, tile.WALL);
        this.vertical_tiles(1, 6, 7, tile.WALL);
        this.vertical_tiles(17, 4, 7, tile.WALL);
        this.horizontal_tiles(6, 8, 14, tile.WALL);
    }

    // obtain HTML text to display the grid map
    get_display_map() {
        let text = '<div id="grid-container">';
        for (let i = 0, id = 0; i < this.rows_count; i++) {
            for (let j = 0; j < this.columns_count; j++, id++) {
                text += '<div';
                // display wall location (valid for both new and old implementations)
                if (document.getElementById('game_implement').checked && this.tile_action == tile.WALL &&
                    this.map_array[i][j] == tile.GRASS && this.belong_wall(j, i) && this.belong_old_wall(j, i)) {
                    text += ' class="' + tile.BOTH_WALL + '-tile"';
                }
                // display wall location (valid only for new implementation)
                else if (this.tile_action == tile.WALL && this.map_array[i][j] == tile.GRASS && this.belong_wall(j, i)) {
                    text += ' class="' + tile.WALL + '-tile"';
                }
                // display wall location (valid only for old implementation)
                else if (document.getElementById('game_implement').checked && this.tile_action == tile.WALL &&
                    this.map_array[i][j] == tile.GRASS && this.belong_old_wall(j, i)) {
                    text += ' class="' + tile.OLD_WALL + '-tile"';
                }
                // display future painted area
                else if (this.tile_action != tile.WALL && this.belong_painting(j, i)) {
                    text += ' class="' + this.tile_action + '-tile"';
                }
                // display normal tile 
                else {
                    text += ' class="' + this.map_array[i][j] + '-tile"';
                }
                text += ' id=' + id; // store ID of this tile
                text += ' onmouseover="over_grid(this)"'; // update when hovering
                text += '></div>';
            }
        }
        text += '</div>';

        return text;
    }

    // update the wall choice to the next one
    update_wall_choice() {
        switch (this.wall_choice) {
            case wall_choice.DIAGONAL_1:
                this.wall_choice = wall_choice.DIAGONAL_2;
                break;

            case wall_choice.DIAGONAL_2:
                this.wall_choice = wall_choice.NO_DIAGONAL_1;
                break;

            case wall_choice.NO_DIAGONAL_1:
                this.wall_choice = wall_choice.NO_DIAGONAL_2;
                break;

            case wall_choice.NO_DIAGONAL_2:
                this.wall_choice = wall_choice.DIAGONAL_1;
                break;

            default:
                break;
        }
    }

    // update the wall end points positions
    wall_end_points() {
        // assume no middle point (i.e. single line wall)
        this.wall_xc = -1;
        this.wall_yc = -1;
        this.wall_line_2 = wall_line.NONE;

        // player is not building a wall
        if (!this.mouse_left_pressed) {
            this.wall_xa = -1;
            this.wall_ya = -1;
            this.wall_xb = -1;
            this.wall_yb = -1;
            this.wall_line_1 = wall_line.NONE;

            this.building = false;
            return;
        }

        // end point on the mouse current location
        this.wall_xb = this.mouse_x;
        this.wall_yb = this.mouse_y;

        if (!this.building) // initiating the wall construction
        {
            // initial point on the mouse current location
            this.wall_xa = this.mouse_x;
            this.wall_ya = this.mouse_y;

            this.wall_line_1 = wall_line.SINGLE;

            this.building = true; // construction just started
            return;
        }

        // difference in coordinates
        let dx = this.wall_xb - this.wall_xa;
        let dy = this.wall_yb - this.wall_ya;

        if (dx == 0 && dy == 0) // single tile
        {
            this.wall_line_1 = wall_line.SINGLE;
        } else if (dx == 0) // vertical
        {
            this.wall_line_1 = wall_line.VERTICAL;
        } else if (dy == 0) // horizontal
        {
            this.wall_line_1 = wall_line.HORIZONTAL;
        } else if (dx == dy || dx == -dy) // diagonal
        {
            this.wall_line_1 = wall_line.DIAGONAL;
        }
        // intermediate point needed
        else {
            switch (this.wall_choice) {
                case wall_choice.DIAGONAL_1: // diagonal attached to point A
                    {
                        let d = Math.min(Math.abs(dx), Math.abs(dy));

                        this.wall_xc = this.wall_xa + Math.sign(dx) * d;
                        this.wall_yc = this.wall_ya + Math.sign(dy) * d;

                        this.wall_line_1 = wall_line.DIAGONAL;
                        this.wall_line_2 = (Math.abs(dx) > Math.abs(dy)) ? wall_line.HORIZONTAL : wall_line.VERTICAL;
                    }
                    break;

                case wall_choice.DIAGONAL_2: // diagonal attached to point B
                    {
                        let d = Math.min(Math.abs(dx), Math.abs(dy));

                        this.wall_xc = this.wall_xb - Math.sign(dx) * d;
                        this.wall_yc = this.wall_yb - Math.sign(dy) * d;

                        this.wall_line_1 = (Math.abs(dx) > Math.abs(dy)) ? wall_line.HORIZONTAL : wall_line.VERTICAL;
                        this.wall_line_2 = wall_line.DIAGONAL;
                    }
                    break;

                case wall_choice.NO_DIAGONAL_1: // vertical attached to point A, horizontal attached to point B
                    {
                        this.wall_xc = this.wall_xa;
                        this.wall_yc = this.wall_yb;

                        this.wall_line_1 = wall_line.VERTICAL;
                        this.wall_line_2 = wall_line.HORIZONTAL;
                    }
                    break;

                case wall_choice.NO_DIAGONAL_2: // horizontal attached to point A, vertical attached to point B
                    {
                        this.wall_xc = this.wall_xb;
                        this.wall_yc = this.wall_ya;

                        this.wall_line_1 = wall_line.HORIZONTAL;
                        this.wall_line_2 = wall_line.VERTICAL;
                    }
                    break;

                default:
                    break;
            }
        }
    }

    // check if tile belongs to a specific wall line
    belong_wall_line(line_type, x1, y1, x2, y2, x, y) {
        switch (line_type) {
            case wall_line.SINGLE:
                return (x == x1 && y == y1) && (x == x2 && y == y2);

            case wall_line.HORIZONTAL:
                return (y == y1 && y == y2) && ((x1 <= x && x <= x2) || (x2 <= x && x <= x1));

            case wall_line.VERTICAL:
                return (x == x1 && x == x2) && ((y1 <= y && y <= y2) || (y2 <= y && y <= y1));

            case wall_line.DIAGONAL:
                return (Math.abs(x - x1) == Math.abs(y - y1)) && (Math.abs(x - x2) == Math.abs(y - y2)) && ((x1 <= x && x <= x2) ||
                    (x2 <= x && x <= x1)) && ((y1 <= y && y <= y2) || (y2 <= y && y <= y1));

            default:
                return false;
        }
    }

    // check if tile belongs to the wall being built (new version)
    belong_wall(x, y) {
        // no valid wall line
        if (this.wall_xa == -1 || this.wall_ya == -1 || this.wall_xb == -1 || this.wall_yb == -1 || this.wall_line_1 == wall_line.NONE) {
            return false;
        }

        // only a single line
        if (this.wall_xc == -1 || this.wall_yc == -1 || this.wall_line_2 == wall_line.NONE) {
            return this.belong_wall_line(this.wall_line_1, this.wall_xa, this.wall_ya, this.wall_xb, this.wall_yb, x, y);
        }
        // two parts for the wall
        else {
            return this.belong_wall_line(this.wall_line_1, this.wall_xa, this.wall_ya, this.wall_xc, this.wall_yc, x, y) ||
                this.belong_wall_line(this.wall_line_2, this.wall_xc, this.wall_yc, this.wall_xb, this.wall_yb, x, y);
        }
    }

    // check if tile belongs to the wall being built (old version)
    belong_old_wall(x, y) {
        // no valid wall line
        if (this.wall_xa == -1 || this.wall_ya == -1 || this.wall_xb == -1 || this.wall_yb == -1 || this.wall_line_1 == wall_line.NONE) {
            return false;
        }

        // only a single line
        if (this.wall_xc == -1 || this.wall_yc == -1 || this.wall_line_2 == wall_line.NONE) {
            return this.belong_wall_line(this.wall_line_1, this.wall_xa, this.wall_ya, this.wall_xb, this.wall_yb, x, y);
        }
        // two parts for the wall
        else {
            // difference in coordinates larger along the X axis
            if (Math.abs(this.wall_xb - this.wall_xa) > Math.abs(this.wall_yb - this.wall_ya)) {
                return this.belong_wall_line(wall_line.HORIZONTAL, this.wall_xa, this.wall_ya, this.wall_xb, this.wall_ya, x, y) ||
                    this.belong_wall_line(wall_line.VERTICAL, this.wall_xb, this.wall_ya, this.wall_xb, this.wall_yb, x, y);
            }
            // difference in coordinates larger along the Y axis
            {
                return this.belong_wall_line(wall_line.VERTICAL, this.wall_xa, this.wall_ya, this.wall_xa, this.wall_yb, x, y) ||
                    this.belong_wall_line(wall_line.HORIZONTAL, this.wall_xa, this.wall_yb, this.wall_xb, this.wall_yb, x, y);
            }
        }
    }

    // build wall when releasing mouse left button
    build_wall() {
        if (this.building && this.tile_action == tile.WALL) {
            for (let i = 0; i < this.rows_count; i++) {
                for (let j = 0; j < this.columns_count; j++) {
                    if (this.map_array[i][j] == tile.GRASS && this.belong_wall(j, i)) {
                        this.map_array[i][j] = tile.WALL;
                    }
                }
            }
            this.building = false; // building action finished 
        }
    }

    // compute painting area
    painting_area() {
        // player is not painting tiles
        if (!this.mouse_left_pressed) {
            this.paint_xa = -1;
            this.paint_ya = -1;
            this.paint_xb = -1;
            this.paint_yb = -1;

            this.painting = false;
            return;
        }

        // end point on the mouse current location
        this.paint_xb = this.mouse_x;
        this.paint_yb = this.mouse_y;

        if (!this.painting) // initiating the tiles painting
        {
            // initial point on the mouse current location
            this.paint_xa = this.mouse_x;
            this.paint_ya = this.mouse_y;

            this.painting = true; // painting just started
        }
    }

    // check if tile belongs to the painting area
    belong_painting(x, y) {
        // valid IO
        if (this.paint_xa == -1 || this.paint_ya == -1 || this.paint_xb == -1 || this.paint_yb == -1) {
            return false;
        }

        return ((this.paint_xa <= x && x <= this.paint_xb) || (this.paint_xb <= x && x <= this.paint_xa)) &&
            ((this.paint_ya <= y && y <= this.paint_yb) || (this.paint_yb <= y && y <= this.paint_ya));
    }

    // paint all the selected tiles with selected type
    paint_tiles() {
        if (this.painting && this.tile_action != tile.WALL) {
            for (let i = 0; i < this.rows_count; i++) {
                for (let j = 0; j < this.columns_count; j++) {
                    if (this.belong_painting(j, i)) {
                        this.map_array[i][j] = this.tile_action;
                    }
                }
            }
            this.painting = false; // painting action finished 
        }
    }
}

// create new instance of the grid computation
let grid = new GridComputation(15, 20);

// update mouse position when hovering over the grid
function over_grid(e) {
    grid.mouse_x = e.id % grid.columns_count;
    grid.mouse_y = (e.id - grid.mouse_x) / grid.columns_count;
}

// reset mouse position
function reset_mouse() {
    grid.reset_mouse();
}

// update when outside the grid
document.getElementById("grid_map_container").addEventListener("mouseout", reset_mouse);

// detect mouse down button
document.onmousedown = function(eventData) {
    if (eventData.button == 0) // left button
    {
        grid.mouse_left_pressed = true;
    } else if (eventData.button == 2) // right button
    {
        grid.mouse_right_pressed = true;
    }
}

// detect mouse up button
document.onmouseup = function(eventData) {
    if (eventData.button == 0) // left button
    {
        grid.mouse_left_pressed = false;
        grid.build_wall(); // build wall
        grid.paint_tiles(); // check if tile must be painted
    } else if (eventData.button == 2) // right button
    {
        grid.mouse_right_pressed = false;
    }
}

// prevent default behavior of the right click (when building wall)
window.addEventListener('contextmenu', function(e) {
    if (grid.building) {
        e.preventDefault();
    }
}, false);

// update wall configuration with mouse wheel (when building wall)
window.addEventListener('wheel', function(e) {
    if (grid.building) {
        e.preventDefault();
        grid.update_wall_choice();
    }
});

// clear the map with only grass
function clear_map() {
    grid.clear_map();
}

// reset the map to its initial value
function reset_map() {
    grid.initial_map();
}

// main update function
function update() {
    // check mouse buttons
    grid.check_mouse_buttons();

    // read options for the tiles
    grid.read_tile_option();

    // compute wall end points
    if (grid.tile_action == tile.WALL) {
        grid.wall_end_points();
        grid.painting = false;
    }
    // compute painting tiles
    else {
        grid.painting_area();
        grid.building = false;
    }

    // get map display
    document.getElementById("grid_map").innerHTML = grid.get_display_map();
}

// update function called each 10 ms
setInterval(update, 10);
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.