diff game.js @ 0:1eef88068f9f tip

initial commit of maze game source
author ferencd
date Sun, 15 Sep 2019 11:46:47 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/game.js	Sun Sep 15 11:46:47 2019 +0200
@@ -0,0 +1,1593 @@
+const pic_size = 64; // The size of 1 cell in the maze
+
+// initial position of the player is always: (0,0) ie. 12px 12px considering the wall size the the top and left
+let x = 12;
+let y = 12;
+
+// moving direction of the player
+var x_delta = 0;
+var y_delta = 0;
+
+// player location in grid
+var col = 0; // The column in the maze where the player is
+var row = 0; // The row in the maze where the player is
+
+// Prepare the canvas
+var canvas = document.getElementById("canvas");
+var canvas_container = document.getElementById("canvasdiv");
+var context = canvas.getContext('2d');
+
+// canvas size calculation
+var canvas_calc_width = w * pic_size ;
+var canvas_calc_height = h * pic_size;
+
+canvas.style.width = canvas_calc_width + "px";
+canvas.style.height = canvas_calc_height + "px";
+
+canvas.width = canvas_calc_width;
+canvas.height = canvas_calc_height;
+
+// Approximates the last row/col drawn for the canvas scrolling
+var last_row_drawn = canvas_container.offsetHeight / pic_size;
+var first_row_drawn = 0;
+var last_col_drawn = canvas_container.offsetWidth / pic_size;
+var first_col_drawn = 0;
+
+// fill the canvas with black
+context.fillStyle = "black";
+context.fillRect(0, 0, canvas.width, canvas.height);
+
+// constants for direction checking
+const N = 1;
+const S = 2;
+const E = 4;
+const W = 8;
+
+// Corner constants, to know where to put a torch
+const TOP_LEFT = 1;
+const TOP_RIGHT = 2;
+const BOTTOM_LEFT = 4;
+const BOTTOM_RIGHT = 8;
+
+// How far must we be from the maze edge to trigger scrolling
+const MAZE_EDGE_DISTANCE_SCROLL_TRIGGER = 4;
+
+// How much we can see from the maze
+var LIGHT_RADIUS = 3;
+
+// how the maze looks
+const FULL_FOG = 0;
+const FULL_DRAWN = 1;
+const FOG_DRAWN = 2;
+
+// indexes of the various directions the player can go
+const MOVE_IDX_LEFT = 0;
+const MOVE_IDX_UP = 1;
+const MOVE_IDX_RIGHT = 2;
+const MOVE_IDX_DOWN = 3;
+
+// Player state: Dead/Alive
+const PLAYER_ALIVE = 1;
+const PLAYER_DIED = 2;
+var player_state = PLAYER_ALIVE;
+
+// Player weapon
+const WEAPON_NONE = -1;
+const WEAPON_SPEAR = 0;
+
+var player_weapon = WEAPON_NONE;
+
+// Player armor
+const ARMOR_NONE = -1;
+const ARMOR_CHAINMAIL = 1;
+const SHOES = 2;
+const RING = 3;
+var player_armor = ARMOR_NONE;
+
+// whether we remove life from steps or not
+const STEPS_COST = 0;       // each step is 1 life
+const STEPS_FREE = 1;       // steps do not cost 1 life
+const STEPS_SICK = 2;       // player is sick, steps cost 2 life
+var player_steps = STEPS_COST;
+var step_count = 0;
+
+const TIME_HAS_EFFECT = 0;
+const TIME_HAS_NO_EFFECT = 1;
+var time_effect = TIME_HAS_EFFECT;
+
+const GAME_SUSPENDED = 1;
+const GAME_RUNNING = 0;
+var game_state = GAME_SUSPENDED;
+
+var time_passing_timeout = null;
+
+// These correspond to specific igw types:
+// 0 - empty handed skeleton. Can be killed with SPEAR or anything above
+// 1 - skeleton with spear. Can be killed with Spear but only if player has armor
+// 2 - skeleton with bow. Does not move, just shoots. Can be killed with spear and armor
+// 3 - skeletong with spear and armor. Cannot be killed
+
+function init_maze_draw_array()
+{
+    var r = new Array(h);
+    for(var j=0; j<h; j++)
+    {
+        r[j] = new Array(w);
+        for(var i=0; i<w; i++)
+        {
+            r[j][i] = FULL_FOG;
+        }
+    }
+    return r;
+}
+
+function update_step_visuals()
+{
+    document.getElementById("steps_passed").innerHTML = " Steps: " + step_count.toString();
+}
+
+function update_life_visuals(current_life)
+{
+    document.getElementById("energy").innerHTML = current_life.toString();
+    document.getElementById("lifeprg").value = current_life;
+}
+
+var dying_plyr_img_idx = 0;
+var killer_igwidx = -1;
+var dancing_kille_igw = 0;
+var dancing_mod = 0;
+var death_wall_drawn = false;
+var skdc = 0; // skeleton dancer index, ie. the one rotating the skeleton
+function player_dies() {
+    context.putImageData(imgDataPrev, x, y);  // clear canvas
+
+    if (dying_plyr_img_idx < 6)
+    {
+
+        context.drawImage(dying_player[dying_plyr_img_idx], x, y);
+        dying_plyr_img_idx ++;
+    }
+
+    if(killer_igwidx !== -1) {
+        if (!death_wall_drawn) {
+            draw_a_wall(row, col);
+            death_wall_drawn = true;
+        }
+
+        dancing_mod ++;
+        context.drawImage(skel_dancer[skdc][dancing_kille_igw], x, y);
+
+        if(dancing_mod % 3)
+        {
+            dancing_kille_igw++;
+            if(dancing_kille_igw === 6)
+            {
+                dancing_kille_igw = 0;
+                skdc ++;
+                if(skdc === 4)
+                {
+                    skdc = 0;
+                }
+            }
+        }
+    }
+
+    requestAnimationFrame(player_dies);
+}
+
+function kill_igw(i)
+{
+    igw[i].state = DEAD;
+    var current_kills = parseInt(document.getElementById("skels_killed").innerHTML);
+    current_kills ++;
+    document.getElementById("skels_killed").innerHTML = current_kills.toString();
+}
+
+var go_texts=["Maybe you shouldn't have had eaten that mushroom.<p>Not all food is safe down here.",
+    "The <img src='/img/skel/wl/d_wl_1.png' title='... it is a spear ...' style='vertical-align:middle;'> is an easy prey when you have a <img src='/img/weapons/spear.png' title='... it is a spear ...' style='vertical-align:middle;'>.<p>Wearing <img src='/img/weapons/armor.png' title='... the chainmail ...' style='vertical-align:middle;'> also increases your chance of survival.<p>Otherwise ... you are easy prey to them.",
+    "You definitely should have eaten something on the way.<p>Finding the <img src='/img/weapons/shoe.png' title='Boots of Lightness' style='vertical-align:middle;'> and the <img src='/img/weapons/ring.png' title='Ring of Health' style='vertical-align:middle;'> also helps.",
+    leave_text
+];
+
+
+const GO_BAD_FOOD = 1;
+const GO_SKELETON = 2;
+const GO_FATIGUE = 3;
+const GO_LEVEL_DONE = 4;
+
+// reason: 1 = player died since he ate something he wasn't supposed to
+//         2 = player was killed by a skeleton
+//         3 = fatigue
+//         4 = player finished the current level
+function game_over(reason, i)
+{
+    if(reason === GO_SKELETON)
+    {
+        killer_igwidx = i;
+        context.putImageData(igw[killer_igwidx].savedImage, igw[killer_igwidx].x, igw[killer_igwidx].y);
+    }
+    document.getElementById("goimg").style.visibility = 'visible';
+
+    var final_message = go_texts[reason - 1];
+    if(reason !== GO_LEVEL_DONE)
+    {
+        update_life_visuals(0);
+
+        player_dies();
+        draw_a_wall(row,col);
+        context.drawImage(dying_player[5], x, y);
+
+        final_message += story_text;
+        document.getElementById("goimg").src ="/img/gameover.png";
+        player_state = PLAYER_DIED;
+    }
+    else
+    {
+        document.getElementById('gonextlevel').style.visibility='visible';
+        clearTimeout(time_passing_timeout);
+    }
+
+    if(game_type === GAME_TYPE_TIMERUN)
+    {
+        final_message += "<p>" + document.getElementById("time_passed").innerHTML;
+    }
+
+    document.getElementById("messages").style.visibility = 'visible';
+    document.getElementById("messages").style.display = 'block';
+    document.getElementById("gotext1").style.visibility = 'visible';
+    document.getElementById("gotext1").innerHTML = final_message;
+    document.getElementById("gospan").style.visibility = 'hidden';
+
+    document.getElementById("sysmenu").style.visibility = 'hidden';
+
+    game_state = GAME_SUSPENDED;
+}
+
+var maze_stats = init_maze_draw_array();
+
+function point_in_circle(center_x, center_y, radius, x, y)
+{
+    var D = Math.sqrt(Math.pow(center_x - x, 2) + Math.pow(center_y - y, 2));
+    return D <= radius
+}
+
+function draw_torches(next)
+{
+    for(var i=0; i<torches.length; i++) {
+        if(next) {
+            torches[i].ctr ++;
+        }
+        if(torches[i].ctr % 5 === 0)
+        {
+            context.putImageData(torches[i].backgr, torches[i].x, torches[i].y);
+
+            if(next) {
+                torches[i].anim_idx ++;
+            }
+
+            if(torches[i].anim_idx === 3 && next) {
+                torches[i].anim_idx = 0;
+            }
+            context.drawImage(torch_images[torches[i].anim_idx], torches[i].x, torches[i].y);
+        }
+    }
+}
+
+function draw_a_wall(saver, savec)
+{
+    if(maze_stats[saver][savec] === FULL_FOG)
+    {
+        return;
+    }
+
+    if(maze_stats[saver][savec] === FULL_DRAWN)
+    {
+        var current_wall = wall_images[ maze[saver][savec] ];
+        // Any door here?
+        let door_t = door_at(savec, saver);
+        if( door_t !== -1 )
+        {
+            current_wall = get_doored_wall(maze[saver][savec], door_t);
+        }
+        context.drawImage(current_wall, savec * pic_size, saver * pic_size);
+        draw_extra_objects(saver, savec, savec * pic_size, saver * pic_size);
+    }
+    else
+    {
+        context.drawImage(fog_drawn_wall_images[ maze[saver][savec] ],
+            savec * pic_size, saver * pic_size);
+    }
+}
+
+// The torch animations
+var torches = [];
+
+var top_btm_chooser = [];
+top_btm_chooser[0] = top_closed_doors;
+top_btm_chooser[1] = bottom_closed_doors;
+
+var small_fellow = new Image();
+small_fellow.src = '/img/funnyfellow.png';
+
+// index is the number of the cell we are looking for, type is whether the door is on
+// the top part of the cell (0) or the bottom part (1)
+function get_doored_wall(index, type)
+{
+    if(type !== 5)
+    {
+        for(var i=0; i<top_btm_chooser[type].length; i++)
+        {
+            if(top_btm_chooser[type][i].idx === index)
+            {
+                return top_btm_chooser[type][i].img;
+            }
+        }
+        return wall_images[ index ];
+    }
+    else
+    {
+        return stairs_down[index];
+    }
+}
+
+// returns the torch type number if we have a torch at this location
+function have_torch_here(ii, jj)
+{
+    for(var i=0; i<torch_placements.length; i++)
+    {
+        if(torch_placements[i].i === ii && torch_placements[i].j === jj)
+        {
+            return torch_placements[i].p
+        }
+    }
+    return 0;
+}
+
+// returns the food type number if we have a food item at this location
+function have_food_here(r, c)
+{
+    for(var i=0; i<food.length; i++)
+    {
+        if(food[i].r === r && food[i].c === c)
+        {
+            return food[i].t;
+        }
+    }
+    return -1;
+}
+
+function have_loot_here(r, c)
+{
+    for(var i=0; i<loot.length; i++)
+    {
+        if(loot[i].r === r && loot[i].c === c)
+        {
+            return loot[i].t;
+        }
+    }
+    return -1;
+}
+
+function draw_food(x, y, t)
+{
+    context.drawImage(food_image[t], x  + (pic_size - 24) / 2 - food_image[t].clientWidth / 2,
+        y  + (pic_size -24)/ 2 - food_image[t].clientHeight / 2);
+}
+
+function draw_loot(x, y, t)
+{
+    context.drawImage(item_image[t], x  + (pic_size - 24) / 2 - item_image[t].clientWidth / 2,
+        y  + (pic_size -24)/ 2 - item_image[t].clientHeight / 2);
+}
+
+// returns the food type number if we have a food item at this location
+function have_weapon_here(r, c)
+{
+    for(var i=0; i<weapon_locations.length; i++)
+    {
+        if(weapon_locations[i].r === r && weapon_locations[i].c === c)
+        {
+            return weapon_locations[i].t;
+        }
+    }
+    return -1;
+}
+
+function draw_weapon(x, y, t)
+{
+    context.drawImage(weapon_images[t], x  + (pic_size - 24) / 2 - weapon_images[t].clientWidth / 2,
+        y  + (pic_size -24)/ 2 - weapon_images[t].clientHeight / 2);
+}
+
+function draw_torch(torch_x, torch_y, i, j, cond)
+{
+    if(cond)
+    {
+        var torch_backgr = context.getImageData(torch_x, torch_y, 6, 10);
+        context.drawImage(torch_images[0], torch_x, torch_y);
+        torches.push({x: torch_x, y: torch_y, anim_idx: 0, ctr: 0, i: i, j: j, backgr: torch_backgr});
+    }
+}
+
+function door_at(i, j)
+{
+    for(var k=0; k<doors.length; k++)
+        if(doors[k].r === j && doors[k].c === i)
+            return doors[k].v;
+    return -1;
+}
+
+// true if we are just drawing a maze
+window.maze_drawing = false;
+
+// true if we are updating the walkers. Don't move the playuer meanwhile
+window.walkers_updating = false;
+
+function draw_extra_objects(j, i, mx, my)
+{
+    var food_type = have_food_here(j, i);
+    if (food_type !== -1) {
+        draw_food(mx, my, food_type);
+    }
+
+    var loot_type = have_loot_here(j, i);
+    if (loot_type !== -1) {
+        draw_loot(mx, my, loot_type);
+    }
+
+    var weapon_type = have_weapon_here(j, i);
+    if (weapon_type !== -1) {
+        draw_weapon(mx, my, weapon_type);
+    }
+}
+
+var small_fellow_needs_to_be_drawn = true;
+if(game_type !== GAME_TYPE_STORY)
+{
+    small_fellow_needs_to_be_drawn = false;
+}
+var ffx = 0;    // funny fellow x,y
+var ffy = 0;
+var ffdx = 0;   // funny fellow deltax,deltay
+var ffdy = 0;
+var ffImgDataPrev = null;
+
+function draw_maze(mid_col, mid_row, force)
+{
+    window.maze_drawing = true;
+    var mx = 0;
+    var my = 0;
+
+//    var strow = Math.max(mid_row - LIGHT_RADIUS - 1, 0);
+//    var stcol = Math.max(mid_col - LIGHT_RADIUS - 1, 0);
+    for(var j=0; j<h; j++) // j - row
+//    for(var j=strow; j<mid_row + LIGHT_RADIUS + 1; j++) // j - row
+    {
+//        for (var i = stcol; i < mid_col + LIGHT_RADIUS + 1; i++) // i - col
+        for (var i = 0; i <w; i++) // i - col
+        {
+            mx = i * pic_size;
+	        my = j * pic_size;
+
+	        var current_idx = maze[j][i];
+            var current_wall = wall_images[ current_idx ];
+
+            if( point_in_circle(mid_col, mid_row, LIGHT_RADIUS, i, j) )
+            {
+                if( maze_stats[j][i] !== FULL_DRAWN || force)
+                {
+                    maze_stats[j][i] = FULL_DRAWN;
+
+                    var door_t = door_at(i, j);
+                
+                    // Any door here?
+                    if(door_t !== -1)
+                    {
+                        current_wall = get_doored_wall(current_idx, door_t);
+                    }
+                    context.drawImage(current_wall, mx, my);
+
+                    // let's see if this is the last cell, ie. stairs down
+                    if(door_t === 5 && small_fellow_needs_to_be_drawn)
+                    {
+                        //1,8,9
+                        ffx = mx + 15;
+                        ffy = my + 15;
+                        if(current_idx === 1 || current_idx === 9) // small guy will stand above the stairs
+                        {
+                            ffy = ffy - pic_size;
+                            ffdy = 1;
+                        }
+                        else    // small guy will stand on the left of it
+                        {
+                            ffx = ffx - pic_size;
+                            ffdx = 1;
+                        }
+                        ffImgDataPrev = context.getImageData(ffx,ffy, anim_size, anim_size);
+                        context.drawImage(small_fellow, ffx, ffy);
+                    }
+
+                    // Torches lying around the corner?
+                    var torch_location_in_cell = have_torch_here(i,j);
+                    if(torch_location_in_cell !== 0)
+                    {
+                        draw_torch(mx, my, i, j, torch_location_in_cell & TOP_LEFT);
+                        draw_torch(mx, my + pic_size - 22, i, j, torch_location_in_cell & BOTTOM_LEFT);
+                        draw_torch(mx+ pic_size - 10, my, i, j, torch_location_in_cell & TOP_RIGHT);
+                        draw_torch(mx + pic_size - 10, my + pic_size - 22, i, j, torch_location_in_cell & BOTTOM_RIGHT);
+                    }
+                    draw_extra_objects(j, i, mx, my);
+                }
+            }
+            else
+            {
+                if(point_in_circle(mid_col, mid_row, LIGHT_RADIUS + 2, i, j) )
+                {
+                    if(maze_stats[j][i] === FULL_DRAWN || (maze_stats[j][i] === FOG_DRAWN && force) )
+                    {
+                        context.drawImage(fog_drawn_wall_images[ current_idx ], mx, my);
+                        maze_stats[j][i] = FOG_DRAWN;
+                        // and remove the torch if found at i,j
+                        for(var ti=0; ti < torches.length; ti++)
+                        {
+                            if(torches[ti].i === i && torches[ti].j === j)
+                            {
+                                torches.splice(ti, 1);
+                            }
+                        }
+                    }
+                }
+            }
+	    }
+	}
+
+	window.maze_drawing = false;
+}
+
+// true if we are in between animation of the player
+// Will be "window.animation_running" in scripts
+var animation_running = false;
+
+// the current animation counter
+var current_anim_counter = 0;
+
+// the direction in which the player is going, indexes into the array of images
+var player_dir = MOVE_IDX_RIGHT; // 0 - Left, 1 - Up, 2 - Right, 3 - Down
+
+// The size of the animation frame, ie. what must be saved from the canvas
+var anim_size = pic_size / 2;
+
+var player_imgset = [lr_player, lr_player_spear, lr_player_armor_spear,
+                    lr_player_armor, lr_player_shoes, lr_player_shoes_spear, // +6 will give the thrust images
+                    lr_player_thrust, lr_player_spear_thrust, lr_player_armor_spear_thrust,
+                    lr_player_armor_thrust, lr_player_shoes_thrust, lr_player_shoes_spear_thrust
+];
+var player_imgset_index = 0;
+
+// returns the current player image according to
+// direction and current animation counter
+var anim_modder = step_anim_cnt;
+function get_current_player_image(dir)
+{
+	return player_imgset[player_imgset_index][dir][current_anim_counter %  anim_modder];
+}
+
+function get_direction(c,fwd) {
+    if(fwd === 1)
+    {
+        if(c === 'N') return N;
+        if(c === 'S') return S;
+        if(c === 'E') return E;
+        if(c === 'W') return W;
+    }
+    else
+    {
+        if(c === 'N') return S;
+        if(c === 'S') return N;
+        if(c === 'E') return W;
+        if(c === 'W') return E;
+    }
+    return 0;
+}
+
+function get_dir_idx(dir)
+{
+    if(dir === W) return MOVE_IDX_LEFT;
+    if(dir === N) return MOVE_IDX_UP;
+    if(dir === E) return MOVE_IDX_RIGHT;
+    if(dir === S) return MOVE_IDX_DOWN;
+    return -1;
+}
+
+const WALKING = 1;      // IGW normally goes around
+const DEAD = 5;         // igw was killed
+
+// in game walkers
+var igw = [];
+
+
+function update_igw_location(i) {
+    switch(igw[i].dir) {
+        case N:
+            igw[i].r --;
+            break;
+        case E:
+            igw[i].c ++;
+            break;
+        case S:
+            igw[i].r ++;
+            break;
+        case W:
+            igw[i].c --;
+            break;
+    }
+}
+
+function init_walkers() {
+    for(var i=0; i<walkers_count; i++)  {
+        var wx = walkers[i].c * pic_size + 12;
+        var wy = walkers[i].r * pic_size + 12;
+
+        var cwalker = {
+            r:walkers[i].r,
+            c:walkers[i].c,
+            saver:-1,
+            savec:-1,
+            t:walkers[i].t,
+            p:walkers[i].p,
+            dir:get_direction(walkers[i].p[0], 1),
+            anim_ctr:0,
+            step_cnt:9,
+            x:wx,
+            y:wy,
+            savedImage:null,
+            path_ctr:0,
+            path_len:walkers[i].path_len,
+            move_dir:1,
+            state:WALKING,
+            just_updated: false,
+            anim_mod:true,
+        };
+
+        igw.push(cwalker);
+    }
+
+    // Now patch the rows and cols for the walker to reflect the first step
+    for(i=0; i<walkers_count; i++) {
+        update_igw_location(i);
+    }
+}
+
+function move_igw(i) {
+    switch(igw[i].dir) {
+        case N:
+            igw[i].y --;
+            return;
+        case E:
+            igw[i].x ++;
+            return;
+        case W:
+            igw[i].x --;
+            return;
+        case S:
+            igw[i].y ++;
+            return;
+    }
+    igw[i].just_updated = true;
+}
+
+function can_go(fromrow, fromcol, pxd, pyd)
+{
+    if(fromrow < 0) fromrow = 0;
+    if(fromcol < 0) fromcol = 0;
+
+    var cell = maze[fromrow][fromcol];
+    var cango = 0;
+    if(pyd === 1)  cango = cell & S;
+    if(pyd === -1) cango = cell & N;
+    if(pxd === 1) cango = cell & E;
+    if(pxd === -1) cango = cell & W;
+
+    return cango !== 0;
+}
+
+function igw_touches_player(i, dist_comp)
+{
+    var dc = (Math.abs(igw[i].x -x) < 5 && Math.abs(igw[i].y -y)<5 );
+    if(dist_comp)
+    {
+        return dc;
+    }
+    return (( ( igw[i].r === row && igw[i].c === col && igw[i].anim_ctr >= pic_size / 2)
+            || (igw[i].saver === row && igw[i].savec === col)
+        ))
+        || dc;
+}
+
+// Checks whether the player has a corresponding weapon which he can use to kill igw[i].
+// igw[i].t is the type of the igw and if the player weapon > igw[i].t then it can kill.
+function player_has_corresponding_weapon(i)
+{
+    // Fully equipped player will kill everything
+    if (player_armor === ARMOR_CHAINMAIL && player_weapon === WEAPON_SPEAR)
+    {
+        return true;
+    }
+    // player with spear will kill simple skeletons
+    if(player_weapon === WEAPON_SPEAR && igw[i].t === 0)
+    {
+        return true;
+    }
+    return (player_weapon >= igw[i].t);
+}
+
+function player_has_armor()
+{
+    return player_armor === ARMOR_CHAINMAIL;
+}
+
+var anim_mod = 0;
+
+function resolve_weapon(weapon_here) {
+    if (weapon_here === RING) // ring, will stop the time
+    {
+        time_effect = TIME_HAS_NO_EFFECT;
+        document.getElementById("ring_of_health_div").style.visibility = 'visible';
+    }
+    else if (weapon_here === SHOES) // shoes
+    {
+        if (player_armor === ARMOR_NONE) // player has no armor, images shoudl be lr_player_shoes
+        {
+            if(player_weapon === WEAPON_SPEAR)
+            {
+                player_imgset_index = 5;
+            }
+            else
+            {
+                player_imgset_index = 4;
+            }
+        }
+        player_steps = STEPS_FREE;
+        document.getElementById("boots_of_light_div").style.visibility = 'visible';
+        LIGHT_RADIUS = 5;
+    }
+    else if (weapon_here === WEAPON_SPEAR) // spear
+    {
+        player_weapon = WEAPON_SPEAR;
+        if (player_armor === ARMOR_NONE) // player has no armor, images shoudl be lr_player_spear
+        {
+            if(player_steps === STEPS_FREE) // Are there shoes on the player?
+            {
+                player_imgset_index = 5;
+            }
+            else
+            {
+                player_imgset_index = 1;
+            }
+        }
+        else if (player_armor === ARMOR_CHAINMAIL) // player has armor, images should be lr_player_armor_spear
+        {
+            player_imgset_index = 2;
+        }
+    }
+    else if (weapon_here === ARMOR_CHAINMAIL) // found the armor
+    {
+        player_armor = ARMOR_CHAINMAIL;
+        if (player_weapon === WEAPON_SPEAR) {
+            player_imgset_index = 2;
+        }
+        else if (player_weapon === WEAPON_NONE) {
+            player_imgset_index = 3;
+        }
+    }
+}
+
+function resolve_loot(t)
+{
+    var loot_value = item_value[t];
+    var current_gold = parseInt(document.getElementById("gold").innerHTML);
+    current_gold += loot_value;
+    document.getElementById("gold").innerHTML = current_gold.toString();
+}
+
+function igw_kills_player(i)
+{
+    if (!player_has_corresponding_weapon(i))
+    {
+        if(player_has_armor())
+        {
+            let current_life = parseInt(document.getElementById("energy").innerHTML);
+            let temp_health = current_life - 1;
+
+            if (temp_health <= 0)
+            {
+                game_over(GO_SKELETON, i);
+                return true;
+            }
+            update_life_visuals(temp_health);
+            return false;
+        }
+        else
+        {
+            game_over(GO_SKELETON, i);
+            return true;
+        }
+    }
+    else
+    {
+        if(igw_touches_player(i, true)) {
+            kill_igw(i);
+        }
+        return false;
+    }
+
+}
+
+var small_fellow_anim_idx = 0;
+var small_fellow_anim_runs = false;
+
+function walkers_simulation()
+{
+    if(player_state === PLAYER_DIED)
+    {
+        context.drawImage(dying_player[5], x, y);
+        return;
+    }
+
+    if(game_state === GAME_SUSPENDED)
+    {
+        return;
+    }
+
+    if(small_fellow_anim_runs && small_fellow_anim_idx < pic_size)
+    {
+        if(ffImgDataPrev)
+        {
+            context.putImageData(ffImgDataPrev, ffx, ffy);  // clear canvas
+        }
+
+        small_fellow_anim_idx ++;
+        ffx += ffdx;
+        ffy += ffdy;
+
+        ffImgDataPrev = context.getImageData(ffx,ffy, anim_size, anim_size);
+
+        context.drawImage(small_fellow, ffx, ffy);
+
+    }
+
+    // moving player drawing
+    if(animation_running)
+    {
+        if(!walkers_updating)
+        {
+            context.putImageData(imgDataPrev, x, y);  // clear canvas
+            x += x_delta;
+            y += y_delta;
+            anim_mod = anim_mod + 1;
+            if (anim_mod % 4 === 0) current_anim_counter += 1;
+            if (current_anim_counter < pic_size / 4) {
+                imgDataPrev = context.getImageData(x, y, anim_size, anim_size);
+            }
+            else {
+                animation_running = false;
+                current_anim_counter = 0;
+
+                // and here verify what is on the square we arrived to
+
+                // 1. See did we find the exit?
+                if (col === exit_col && row === exit_row) {
+                    game_over(GO_LEVEL_DONE, -1);
+                    return;
+                }
+
+                // 2. Any foodstuff or other here?
+                var food_type_here = have_food_here(row, col);
+                var maze_redraw_needed = false;
+                if (food_type_here !== -1) {
+                    var current_life = parseInt(document.getElementById("energy").innerHTML);
+                    var temp_health = current_life + food_effects[food_type_here];
+                    remove_food(row, col);
+                    maze_redraw_needed = true;
+                    if (temp_health > 100) {
+                        temp_health = 100;
+                    }
+                    if (temp_health <= 0) {
+                        game_over(GO_BAD_FOOD, -1);
+                        return;
+                    }
+
+                    update_life_visuals(temp_health);
+                }
+
+                // Are we next to the small guy with a visible line?
+                if( row > h - 4 && col > w - 4 && game_type === GAME_TYPE_STORY)
+                {
+                    small_fellow_needs_to_be_drawn = false;
+                    maze_redraw_needed = true;
+                    small_fellow_anim_runs = true;
+                }
+
+                // see if there is a wepon there
+                var weapon_here = have_weapon_here(row, col);
+                if (weapon_here !== -1)
+                {
+                    resolve_weapon(weapon_here);
+                    remove_weapon(row, col);
+                    maze_redraw_needed = true;
+                }
+
+                // if this is an adventure game, see if there is any loot here
+                if(game_type === GAME_TYPE_ADVENTURE)
+                {
+                    // see if there is a wepon there
+                    var loot_here = have_loot_here(row, col);
+                    if (loot_here !== -1)
+                    {
+                        resolve_loot(loot_here);
+                        remove_loot(row, col);
+                        maze_redraw_needed = true;
+                    }
+                }
+
+                if (maze_redraw_needed)
+                {
+                    draw_maze(col, row, true);
+                    imgDataPrev = context.getImageData(x, y, anim_size, anim_size);
+                }
+
+                // see if this was a hit operation or not
+                if(anim_modder === thrust_anim_cnt)
+                {
+                    // update the image set for the walking
+                    anim_modder = step_anim_cnt;
+                    player_imgset_index -= 6;
+                }
+            }
+            context.drawImage(get_current_player_image(player_dir), x, y);
+        }
+    }
+
+    draw_torches(true);
+
+    window.walkers_updating = true;
+    var drawn_walkers = [];
+
+    for (var i = 0; i < igw.length; i++) {
+        if (igw[i].state === DEAD) {
+            context.drawImage(skel_dies[5], igw[i].x, igw[i].y);
+            continue;
+        }
+
+        igw[i].anim_mod = !igw[i].anim_mod;
+        if (igw[i].anim_mod) igw[i].anim_ctr++;
+        igw[i].just_updated = false;
+
+        igw[i].saver = igw[i].r;
+        igw[i].savec = igw[i].c;
+
+        if (igw_touches_player(i,false))
+        {
+            if(igw_kills_player(i))
+            {
+                return;
+            }
+        }
+
+        if (igw[i].anim_ctr > pic_size / 2 - 1) {
+            // means we have stepped over the current tile, time to advance to the next one
+            igw[i].path_ctr = igw[i].path_ctr + igw[i].move_dir;
+            // console.log("igw[",i,'].path_ctr=',igw[i].path_ctr,' path_len=',igw[i].path_len);
+            if (igw[i].path_ctr === igw[i].path_len || igw[i].path_ctr < 0) {
+                // just perform a routine check that the last step of the igw does not kill the player
+                var tempr = igw[i].r;
+                var tempc = igw[i].c;
+                update_igw_location(i);
+                if (igw_touches_player(i,false))
+                {
+                    if(igw_kills_player(i))
+                    {
+                        return;
+                    }
+                }
+                //draw_a_wall(igw[i].r, igw[i].c);
+
+                igw[i].r = tempr;
+                igw[i].c = tempc;
+
+                // this reverses the igw
+                igw[i].move_dir = -igw[i].move_dir;
+                igw[i].path_ctr --;
+                if(igw[i].path_ctr < 0)
+                {
+                    igw[i].path_ctr = 0;
+                }
+            }
+
+            igw[i].dir = get_direction(igw[i].p[igw[i].path_ctr], igw[i].move_dir);
+            update_igw_location(i);
+            igw[i].anim_ctr = 0;
+        }
+
+        if (maze_stats[igw[i].r][igw[i].c] === FULL_DRAWN && igw[i].savedImage === null)
+        {
+            igw[i].savedImage = context.getImageData(igw[i].x, igw[i].y, anim_size, anim_size);
+        }
+        else
+        {
+            if (maze_stats[igw[i].r][igw[i].c] === FOG_DRAWN) {
+                context.drawImage(fog_drawn_wall_images[maze[igw[i].r][igw[i].c]], igw[i].c * pic_size, igw[i].r * pic_size);
+            }
+
+            // do we move away from a full drawn cell?
+            if (maze_stats[igw[i].saver][igw[i].savec] === FULL_DRAWN) {
+                draw_a_wall(igw[i].saver, igw[i].savec);
+            }
+            if (igw[i].savedImage === null) {
+                igw[i].savedImage = context.getImageData(igw[i].x, igw[i].y, anim_size, anim_size);
+            }
+
+        }
+
+        // restore the background
+        if( maze_stats[igw[i].r][igw[i].c] === FULL_DRAWN && igw[i].savedImage !== null && maze_stats[igw[i].saver][igw[i].savec] === FULL_DRAWN )
+        {
+            draw_a_wall(igw[i].r, igw[i].c);
+            // draw_extra_objects(igw[i].r, igw[i].c, igw[i].r * pic_size, igw[i].c * pic_size)
+            context.putImageData(igw[i].savedImage, igw[i].x, igw[i].y);
+
+            // draw only torches which are being affected
+            for (var k = 0; k < torches.length; k++) {
+                if (torches[k].i === igw[i].c && torches[k].j === igw[i].r) {
+                    context.drawImage(torch_images[torches[k].anim_idx], torches[k].x, torches[k].y);
+                }
+            }
+        }
+
+        // move the walker on the screen
+        move_igw(i);
+
+        if (maze_stats[igw[i].r][igw[i].c] === FULL_DRAWN) {
+            igw[i].savedImage = context.getImageData(igw[i].x, igw[i].y, anim_size, anim_size);
+            let dir_idx = get_dir_idx(igw[i].dir);
+            let ani_idx = igw[i].anim_ctr % igw[i].step_cnt;
+            // console.log('igw[i].dir',igw[i].dir, 'dir_idx',dir_idx,'ani_idx',ani_idx);
+            context.drawImage(walker_images[igw[i].t][dir_idx][ani_idx], igw[i].x, igw[i].y);
+            drawn_walkers.push({
+                img: walker_images[igw[i].t][dir_idx][igw[i].anim_ctr % igw[i].step_cnt],
+                x: igw[i].x,
+                y: igw[i].y,
+                r: igw[i].r,
+                c: igw[i].c
+            });
+        }
+    }
+
+    // and just draw again all the walkers that were drawn
+    if (drawn_walkers.length > 0) {
+        for (i = 0; i < drawn_walkers.length; i++) {
+            if (maze_stats[drawn_walkers[i].r][drawn_walkers[i].c] === FULL_DRAWN &&
+                maze_stats[igw[i].saver][igw[i].savec] === FULL_DRAWN) {
+                context.drawImage(drawn_walkers[i].img, drawn_walkers[i].x, drawn_walkers[i].y);
+            }
+        }
+        // and the player
+        context.drawImage(get_current_player_image(player_dir), x, y);
+    }
+    window.walkers_updating = false;
+
+    requestAnimationFrame(walkers_simulation);
+}
+
+// previous image which was placed on the canvas
+var imgDataPrev = null;
+
+
+/* Mouse scroll handling */
+// The canvas will scroll back to these coordinates when done with mouse move
+var marginLeftBackup = 0;
+var marginTopBackup = 0;
+var dragging = false;
+var lastX = 0;
+var lastY = 0;
+var marginLeft = 0;
+var marginTop = 0;
+// mouse press handler
+function mouse_press(e)
+{
+    var evt = e || event;
+    dragging = true;
+    lastX = evt.clientX;
+    lastY = evt.clientY;
+    marginLeftBackup = canvas.style.marginLeft;
+    marginTopBackup = canvas.style.marginTop;
+    e.preventDefault();
+}
+
+function mouse_move(e)
+{
+    var evt = e || event;
+    if (dragging) {
+        var deltaX = evt.clientX - lastX;
+        lastX = evt.clientX;
+
+        if(marginLeft + deltaX <= 0 && canvas.width - Math.abs(marginLeft + deltaX) >= canvas_container.offsetWidth) // did we scroll out left/right
+        {
+            marginLeft += deltaX;
+            canvas.style.marginLeft = marginLeft + "px";
+        }
+
+        var deltaY = evt.clientY - lastY;
+        lastY = evt.clientY;
+        if(marginTop + deltaY <= 0 && canvas.height - Math.abs(marginTop + deltaY) >= canvas_container.offsetHeight)
+        {
+            marginTop += deltaY;
+            canvas.style.marginTop = marginTop + "px";
+        }
+    }
+    e.preventDefault();
+}
+
+function mouse_up() {
+    dragging = false;
+    canvas.style.marginLeft = marginLeftBackup;
+    canvas.style.marginTop = marginTopBackup;
+}
+
+var canv_anim_counter = 0;
+var canv_moving_direction_ud = 0;
+function animate_canvas_movement_up_down() {
+    canv_anim_counter += 1;
+    marginTop += canv_moving_direction_ud;
+    if (canv_anim_counter < pic_size)
+    {
+        requestAnimationFrame(animate_canvas_movement_up_down);
+    }
+    else
+    {
+        canv_anim_counter = 0;
+    }
+    if(canv_moving_direction_ud === -1)
+    {
+        if(canvas.height - Math.abs(marginTop) >= canvas_container.offsetHeight)
+        {
+            canvas.style.marginTop = marginTop + "px";
+        }
+    }
+    else
+    {
+        if(marginTop <= 0)
+        {
+            canvas.style.marginTop = marginTop + "px";
+        }
+    }
+}
+
+var canv_moving_direction_lr = 0;
+function animate_canvas_movement_left_right() {
+    canv_anim_counter += 1;
+    marginLeft += canv_moving_direction_lr;
+    if (canv_anim_counter < pic_size)
+    {
+        requestAnimationFrame(animate_canvas_movement_left_right);
+    }
+    else
+    {
+        canv_anim_counter = 0;
+    }
+    if(canv_moving_direction_lr === -1)
+    {
+        if(canvas.width - Math.abs(marginLeft) >= canvas_container.offsetWidth)
+        {
+            canvas.style.marginLeft = marginLeft + "px";
+        }
+    }
+    else
+    {
+        if(marginLeft <= 0)
+        {
+            canvas.style.marginLeft = marginLeft + "px";
+        }
+    }
+}
+
+function remove_food(row, col)
+{
+    for(var i=0; i<food.length; i++)
+    {
+        if(food[i].r === row && food[i].c === col)
+        {
+            food.splice(i, 1);
+            return;
+        }
+    }
+}
+
+function remove_weapon(row, col)
+{
+    for(var i=0; i<weapon_locations.length; i++)
+    {
+        if(weapon_locations[i].r === row && weapon_locations[i].c === col)
+        {
+            weapon_locations.splice(i, 1);
+            return;
+        }
+    }
+}
+
+function remove_loot(row, col)
+{
+    for(var i=0; i<loot.length; i++)
+    {
+        if(loot[i].r === row && loot[i].c === col)
+        {
+            loot.splice(i, 1);
+            return;
+        }
+    }
+}
+var time_pass_timeout_set = false;
+
+function step(dir, px_delta, py_delta)
+{
+    if(!time_pass_timeout_set)
+    {
+        time_passing_timeout = setTimeout(time_tick, 1000);
+        time_pass_timeout_set = true;
+    }
+
+    if(! animation_running) // this tells us if we are in an animation
+    {
+        var current_life = parseInt(document.getElementById("energy").innerHTML);
+
+        player_dir = dir;
+
+        var t_row = row + py_delta;
+        var t_col = col + px_delta;
+        if(can_go(row, col, px_delta, py_delta))
+        {
+
+            if(player_steps === STEPS_COST) {
+                current_life --;
+            }
+            else
+            if(player_steps === STEPS_SICK) {
+                current_life -= 2;
+            }
+            if(current_life <= 0)
+            {
+                game_over(GO_FATIGUE, -1);
+                return;
+            }
+            update_life_visuals(current_life);
+            step_count ++;
+            if(game_type === GAME_TYPE_TIMERUN)
+            {
+                update_step_visuals();
+            }
+
+            var ud_scrolled = false;
+            var lr_scrolled = false;
+
+            if(px_delta === 1) // right
+            {
+                if(col >= last_col_drawn - MAZE_EDGE_DISTANCE_SCROLL_TRIGGER)
+                {
+                    last_col_drawn ++ ;
+                    first_col_drawn ++;
+                    canv_moving_direction_lr = -1;
+                    canv_anim_counter = 0;
+                    animate_canvas_movement_left_right();
+                    lr_scrolled = true;
+                }
+            }
+
+            if(px_delta === -1) // left
+            {
+                if(col <= first_col_drawn + MAZE_EDGE_DISTANCE_SCROLL_TRIGGER && !lr_scrolled && first_col_drawn > 0)
+                {
+                    last_col_drawn -- ;
+                    first_col_drawn --;
+                    canv_moving_direction_lr = 1;
+                    canv_anim_counter = 0;
+                    animate_canvas_movement_left_right();
+                    lr_scrolled = true;
+                }
+            }
+
+            if(py_delta === 1) // down
+            {
+                if(row >= last_row_drawn - MAZE_EDGE_DISTANCE_SCROLL_TRIGGER && !lr_scrolled)
+                {
+                    last_row_drawn ++ ;
+                    first_row_drawn ++;
+                    canv_moving_direction_ud = -1;
+                    canv_anim_counter = 0;
+                    animate_canvas_movement_up_down();
+                    ud_scrolled = true;
+                }
+            }
+
+            if(py_delta === -1) //up
+            {
+                if(row <= first_row_drawn + MAZE_EDGE_DISTANCE_SCROLL_TRIGGER && !lr_scrolled && !ud_scrolled && first_row_drawn > 0)
+                {
+                    last_row_drawn -- ;
+                    first_row_drawn --;
+                    canv_moving_direction_ud = 1;
+                    canv_anim_counter = 0;
+                    animate_canvas_movement_up_down();
+                }
+            }
+
+            row = t_row;
+            col = t_col;
+
+            anim_modder = step_anim_cnt;
+            window.animation_running = true;
+            current_anim_counter = 0;
+            x_delta = px_delta;
+            y_delta = py_delta;
+        }
+
+        // and finally make sure the player is drawn back normally where it's supposed to be
+        draw_maze(col, row, true);
+        context.drawImage(get_current_player_image(player_dir), x, y);
+    }
+}
+
+function sleep(ms)
+{
+    return new Promise(resolve => setTimeout(resolve, ms));
+}
+
+function hit_something()
+{
+    if(! animation_running) // this tells us if we are in an animation
+    {
+        x_delta = 0;
+        y_delta = 0;
+        player_imgset_index += 6;
+        anim_modder = thrust_anim_cnt;
+        window.animation_running = true;
+        current_anim_counter = 0;
+    }
+}
+
+// the keyboard handler
+async function keypressed(e)
+{
+    if(player_state === PLAYER_ALIVE)
+    {
+        let slept = 1;
+        while(window.walkers_updating && slept < 60)
+        {
+            slept ++;
+            await sleep(20);
+        }
+
+        var code = e.keyCode;
+        switch (code) {
+            case 37: step(MOVE_IDX_LEFT, -1, 0); break; //Left key
+            case 38: step(MOVE_IDX_UP, 0, -1); break; //Up key
+            case 39: step(MOVE_IDX_RIGHT, 1, 0); break; //Right key
+            case 40: step(MOVE_IDX_DOWN, 0, 1); break; //Down key
+            case 32: hit_something(); // Space
+
+            default: console.log(code); //Everything else
+        }
+    }
+}
+
+Element.prototype.remove = function() {
+    this.parentElement.removeChild(this);
+};
+NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
+    for(var i = this.length - 1; i >= 0; i--) {
+        if(this[i] && this[i].parentElement) {
+            this[i].parentElement.removeChild(this[i]);
+        }
+    }
+};
+
+function toggle_gos(visible)
+{
+    document.getElementById('gotext1').style.visibility=visible?'visible':'hidden';
+    document.getElementById('gotext2').style.visibility=visible?'visible':'hidden';
+    document.getElementById('gotext3').style.visibility=visible?'visible':'hidden';
+    document.getElementById('gotext4').style.visibility=visible?'visible':'hidden';
+    document.getElementById('gotext5').style.visibility=visible?'visible':'hidden';
+
+}
+
+document.getElementById('badbrowser').remove();
+document.getElementById('gobutton').style.visibility='visible';
+toggle_gos(true);
+
+function time_passes_by()
+{
+    if(player_state === PLAYER_DIED)
+    {
+        context.drawImage(dying_player[5], x, y);
+        return;
+    }
+    if(time_effect === TIME_HAS_EFFECT)
+    {
+        var current_life = parseInt(document.getElementById("energy").innerHTML);
+        current_life --;
+        update_life_visuals(current_life);
+        if(current_life <= 0)
+        {
+            game_over(GO_FATIGUE, -1);
+
+        }
+        else
+        {
+            setTimeout(time_passes_by, 3000);
+        }
+    }
+}
+
+var seconds_passed = 0;
+var minutes_passed = 0;
+var hours_passed = 0;
+var days_passed = 0;
+
+function time_tick()
+{
+    seconds_passed ++;
+    if(seconds_passed === 60)
+    {
+        minutes_passed ++;
+        if(minutes_passed === 60)
+        {
+            hours_passed ++;
+            if(hours_passed === 24)
+            {
+                days_passed ++;
+                hours_passed = 0;
+            }
+            minutes_passed = 0;
+        }
+        seconds_passed = 0;
+    }
+
+    let new_time = hours_passed.toString() + "h : " + minutes_passed.toString() + "m : " + seconds_passed.toString() + "s " + "&nbsp;";
+    if(days_passed > 0)
+    {
+        new_time = days_passed.toString() + "days ";
+    }
+    document.getElementById('time_passed').innerHTML = new_time;
+    time_passing_timeout = setTimeout(time_tick, 1000);
+
+}
+
+function get_current_level() {
+    var lid = document.getElementById('lid').value;
+    var level = parseInt(lid);
+    return {level: level};
+}
+
+function setup_labyrinth(evt)
+{
+    if(game_type === GAME_TYPE_TIMERUN)
+    {
+        time_effect = TIME_HAS_NO_EFFECT;
+        player_steps = STEPS_FREE;
+    }
+
+    var __ret = get_current_level();
+    var level = __ret.level;
+    document.getElementById('levelctr').innerHTML = level.toString();
+
+    var gid = document.getElementById('gid').value;
+    document.getElementById('gameid').innerHTML = "<a href=/" + gid + ">" + gid + "&nbsp;</a>";
+
+    document.getElementById('messages').style.visibility='hidden';
+    document.getElementById('gobutton').style.visibility='hidden';
+
+    toggle_gos(false);
+
+    // draw the maze
+    draw_maze(col, row, false);
+
+    // set up the previous image data in order to save it for the next animation step
+    imgDataPrev = context.getImageData(x,y, anim_size, anim_size);
+
+    // draw the player
+    context.drawImage(get_current_player_image(player_dir), x, y);
+
+    // setting up the event listeners
+    window.addEventListener('keydown', keypressed, false);
+    canvas.addEventListener('mousedown', mouse_press, false);
+    window.addEventListener('mousemove', mouse_move, false);
+    window.addEventListener('mouseup', mouse_up, false);
+
+    init_walkers();
+
+    setTimeout(time_passes_by, 3000);
+
+    game_state = GAME_RUNNING;
+
+    walkers_simulation();
+}
+
+
+function post(path, params, method) {
+    method = method || "post";
+    var form = document.createElement("form");
+    form.setAttribute("method", method);
+    form.setAttribute("action", path);
+
+    for(var key in params) {
+        if(params.hasOwnProperty(key)) {
+            console.log(key, params[key]);
+
+            var hiddenField = document.createElement("input");
+            hiddenField.setAttribute("type", "hidden");
+            hiddenField.setAttribute("name", key);
+            hiddenField.setAttribute("value", params[key]);
+
+            form.appendChild(hiddenField);
+        }
+    }
+
+    document.body.appendChild(form);
+    form.submit();
+}
+
+function go_next_level()
+{
+    var gid = document.getElementById('gid').value;
+    post(window.location.href, {gid: gid});
+}
+
+function show_menu()
+{
+    document.getElementById("messages").style.visibility = 'visible';
+    document.getElementById("messages").style.display = 'block';
+    document.getElementById("sysmenu").style.visibility = 'visible';
+    document.getElementById("sysmenu").style.display = 'block';
+
+    document.getElementById("goimg").src = "/img/dungeonslogo.png";
+}
+
+document.addEventListener('touchstart', handleTouchStart, false);
+document.addEventListener('touchmove', handleTouchMove, false);
+
+var xDown = null;
+var yDown = null;
+
+function handleTouchStart(evt) {
+    xDown = evt.touches[0].clientX;
+    yDown = evt.touches[0].clientY;
+};
+
+function handleTouchMove(evt) {
+    if ( ! xDown || ! yDown ) {
+        return;
+    }
+
+    var xUp = evt.touches[0].clientX;
+    var yUp = evt.touches[0].clientY;
+
+    var xDiff = xDown - xUp;
+    var yDiff = yDown - yUp;
+
+    if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/
+        if ( xDiff > 0 ) {
+            step(MOVE_IDX_LEFT, -1, 0);
+        } else {
+            step(MOVE_IDX_RIGHT, 1, 0);
+        }
+    } else {
+        if ( yDiff > 0 ) {
+            step(MOVE_IDX_UP, 0, -1);
+        } else {
+            step(MOVE_IDX_DOWN, 0, 1);
+        }
+    }
+    /* reset values */
+    xDown = null;
+    yDown = null;
+};