//Still on the TODO list: //Better map loading code //Highscore saving //Automatic loading of next map //Better graphics //Map editor //Get all of the original Sokoban maps //End-game check should check whether all boxes are on a base instead ofchecking if all bases are occupied. //Proper handling of up/down keys + scrollbars //Undo option function $() { return document.getElementById(arguments[0]); } function lpad(n, z) { for (var str = '' + n, i = str.length; i < z; i++) { str = '0' + str; } return str; } var SM_NULL = 0x000; var SM_WALL = 0x01 << 1; // OPT_BACKGROUND|OPT_SOLID var SM_PLAYER = 0x01 << 2; // OPT_PLAYER var SM_BOX = 0x01 << 3; // OPT_SOLID|OPT_MOVABLE var SM_BASE = 0x01 << 4; // OPT_BACKGROUND var SD_FORWARD = 0x01; var SD_BACKWARD = 0x02; var SD_LEFT = 0x03; var SD_RIGHT = 0x04; function Sokoban() { this.grid_width = 0; this.grid_height = 0; this.grid_code = null; this.grid = []; this.player_location = null; this.player_direction = SD_FORWARD; this.base_count = null; this.moves = 0; this.pushes = 0; this.start_time = null; this.end_time = null; this.timer = null; this.grid_size = null; this.undo = null; // Fixme if (window.sb_timer) { clearInterval(window.sb_timer); } window.sb_timer = null; } Sokoban.prototype.get_grid_id = function(k) { var kw = Math.floor(k / this.grid_width); return 'grid-' + kw + '-' + (k - (kw * this.grid_width)); } Sokoban.prototype.grid_ntoc = function(n) { var c0 = Math.floor(n / this.grid_width); return [c0, (n - (c0 * this.grid_width))]; } Sokoban.prototype.grid_cton = function(c) { return (c[0] * this.grid_width) + c[1]; } Sokoban.prototype.render_grid = function() { if (this.grid_code != null) { this.unmap_grid(); this.grid_code = null; } var tmp = '<div id="grid">'; for (var i = 0; i < this.grid_height; i++) { tmp += '<div class="grid-row">\n\n'; for (var j = 0; j < this.grid_width; j++) { tmp += '<div id="grid-' + i + '-' + j + '"></div>'; } tmp += '</div>\n\n'; } tmp += '</div><div id="info"><span id="map">00</span> <span id="moves">Mosse: 0000</span> ' + '<span id="pushes">Spinte: 0000</span> ' + '<span id="time">Tempo: 00:00:00</span>' + '</div>'; $('game').innerHTML = tmp; $('game').style.width = (this.grid_width * 32) + 'px'; this.render_grid_objects(); } Sokoban.prototype.render_grid_objects = function() { for (var k = 0; k < this.grid_size; k++) { try { this.render_grid_object(k); } catch(e) { alert(k + '\n' + this.get_grid_id(k) + '\n' + e); break; } } } Sokoban.prototype.render_grid_object = function(k) { if (this.grid[k] & SM_PLAYER) { switch(this.player_direction) { case SD_LEFT: $(this.get_grid_id(k)).innerHTML = '<img src="sokoban-left.png" alt="" />'; break; case SD_RIGHT: $(this.get_grid_id(k)).innerHTML = '<img src="sokoban-right.png" alt="" />'; break; case SD_FORWARD: $(this.get_grid_id(k)).innerHTML = '<img src="sokoban-forward.png" alt="" />'; break; case SD_BACKWARD: $(this.get_grid_id(k)).innerHTML = '<img src="sokoban-backward.png" alt="" />'; break; } } else if (this.grid[k] & SM_BOX) { $(this.get_grid_id(k)).innerHTML = '<img src="sokoban-box-' + (this.grid[k] & SM_BASE ? '1' : '0') + '.png" alt="" />'; } else if (this.grid[k] & SM_BASE) { $(this.get_grid_id(k)).innerHTML = '<img src="sokoban-base.png" alt="" />'; } else if (this.grid[k] & SM_WALL) { $(this.get_grid_id(k)).innerHTML = '<img src="sokoban-wall.png" alt="" />'; } else { $(this.get_grid_id(k)).innerHTML = ''; } } Sokoban.prototype.init_player_location = function(k, direction) { if (this.player_location == null) { this.grid[k] = SM_PLAYER; this.player_location = k; this.player_direction = direction; } else { this.grid[k] = SM_NULL; } } Sokoban.prototype.update_moves = function() { if (this.moves == 0) { this.start_time = new Date().getTime() - 500; this.end_time = null; var __timer_hack = this; window.sb_timer = setInterval(function() {__timer_hack.update_time();}, '500'); } this.moves++; $( 'moves' ).innerHTML = 'Mosse: ' + lpad(this.moves, 4); } Sokoban.prototype.update_pushes = function() { this.pushes++; $('pushes').innerHTML = 'Spinte: ' + lpad(this.pushes, 4); } Sokoban.prototype.update_time = function() { var len = 0; if (this.end_time != null) { len = this.end_time - this.start_time; } else { len = new Date().getTime() - this.start_time; } len = Math.floor(len / 1000); var hrs = Math.floor(len / 3600); len -= hrs * 3600; var min = Math.floor(len / 60); len -= min * 60; $('time').innerHTML = 'Tempo: ' + lpad(hrs, 2) + ':' + lpad(min, 2) + ':' + lpad(len, 2); } Sokoban.prototype.unmap_grid = function() { this.base_count = 0; this.grid_size = this.grid_width * this.grid_height; for (var k = 0; k < this.grid_size; k++) { switch(this.grid_code.substr(k, 1)) { case 'X': this.grid[k] = SM_WALL; break; case '0': this.grid[k] = SM_BOX; break; case '1': this.grid[k] = SM_BOX | SM_BASE; this.base_count++; break; case '#': this.grid[k] = SM_BASE; this.base_count++; break; case 'F': this.init_player_location(k, SD_FORWARD); break; case 'B': this.init_player_location(k, SD_BACKWARD); break; case 'L': this.init_player_location(k, SD_LEFT); break; case 'R': this.init_player_location(k, SD_RIGHT); break; default: this.grid[k] = SM_NULL; break; } } } Sokoban.prototype.validate_push = function(m, m_co) { if (this.grid[m] & SM_WALL || this.grid[m] & SM_BOX) { return false; } if (m_co[0] < 0 || m_co[0] >= this.grid_height || m_co[1] < 0 || m_co[1] >= this.grid_width) { return false; } return true; } Sokoban.prototype.validate_move = function(direction) { if (this.player_location == null || this.end_time != null) { return false; } var k = this.player_location; var k_co = this.grid_ntoc(k); var m_co = this.modify_coords([k_co[0], k_co[1]], direction); var m = this.grid_cton(m_co); var egc = 0; var undo = [null, null, this.player_direction]; this.player_direction = direction; if (m_co[0] < 0 || m_co[0] >= this.grid_height || m_co[1] < 0 || m_co[1] >= this.grid_width) { return false; } if (!(this.grid[m] & SM_WALL)) { if (this.grid[m] & SM_BOX) { var p_co = this.modify_coords(m_co, direction), p = this.grid_cton(p_co); if (this.validate_push(p, p_co)) { undo[1] = [m, p]; this.grid[m] ^= SM_BOX; this.grid[p] |= SM_BOX; egc++; this.update_pushes(); this.render_grid_object(m); this.render_grid_object(p); } } if (!(this.grid[m] & SM_BOX)) { undo[0] = [k, m]; this.grid[k] ^= SM_PLAYER; this.grid[m] |= SM_PLAYER; this.player_location = m; egc++; this.update_moves(); this.render_grid_object(k); this.render_grid_object(m); } if (undo[0] != null) { this.undo = undo; } } else { this.render_grid_object(k); } //this.render_grid_objects(); if (egc >= 2) { for (var k = 0, egc = 1; k < this.grid_size; k++) { if (this.grid[k] & SM_BOX && !(this.grid[k] & SM_BASE)) { egc = 0; break; } } if (egc == 1) { this.end_time = new Date().getTime(); clearInterval(window.sb_timer); window.sb_timer = null; this.update_time(); } } } Sokoban.prototype.undo_move = function() { if (this.undo == null) return; if (this.undo[2] != null) { this.player_direction = this.undo[2]; } if (this.undo[0] != null) { var k = this.undo[0][0], m = this.undo[0][1]; this.grid[k] |= SM_PLAYER; this.grid[m] ^= SM_PLAYER; this.player_location = k; this.update_moves(); this.render_grid_object(k); this.render_grid_object(m); } if (this.undo[1] != null) { var m = this.undo[1][0], p = this.undo[1][1]; this.grid[m] |= SM_BOX; this.grid[p] ^= SM_BOX; this.render_grid_object(m); this.render_grid_object(p); } this.undo = null; } Sokoban.prototype.modify_coords = function(coords, direction) { switch (direction) { case SD_LEFT: coords[1]--; break; case SD_RIGHT: coords[1]++; break; case SD_FORWARD: coords[0]--; break; case SD_BACKWARD: coords[0]++; break; } return coords; } /** * These are the original maps, extracted from the DOS Sokoban game */ var sb_maps = [ /*1*/' XXXXX X X X0 X XXX 0XX X 0 0 X XXX X XX X XXXXXXX X XX XXXXX ##XX 0 0 ##XXXXXX XXX XFXX ##X X XXXXXXXXX XXXXXXX ', /*2*/' XXXXXXXXXXXX X## X XXX X## X 0 0 X X## X0XXXX X X## F XX X X## X X 0 XX XXXXXX XX0 0 X X 0 0 0 0 X X X X XXXXXXXXXXXX ', /*3*/' XXXXXXXX X FX X 0X0 XX X 0 0X XX0 0 X XXXXXXXXX 0 X XXX X#### XX 0 0 X XX### 0 0 X X#### XXXXXXXXXX XXXXXXXX ', /*4*/' XXXXXXXX X ####XXXXXXXXXXXXX ####XX X 0 0 ####XX 000X0 0 X ####XX 0 0 X ####XX 00 X0 0 0XXXXXXXXX 0 X X XX XXXXXXXXX X X XX X 0 XX X 00X00 FX X X XX XXXXXXXXXXX ', /*5*/' XXXXX X XXXXX X X0XX X X 0 X XXXXXXXXX XXX X X#### XX 0 0XXX X#### 0 00 XX X#### XX0 0 FX XXXXXXXXX 0 XX X 0 0 X XXX XX X X X XXXXXX ', /*6*/' XXXXXX XXX X## X XXFXX X## XXX X X## 00 X X## X X 0 X X##XXX X 0 X XXXX 0 X0 X X 0X 0 X X 0 0 X X XX X XXXXXXXXX ', /*7*/' XXXXX XXXXXXX XX XX X FXX 00 X X 0 X X 0 XXX X XXX XXXXX0XXX X 0 XXX ##X X 0 0 0 ###X X XXX###X X 00 X X###X X XXX XXXXX XXXX ', /*8*/' XXXX X XXXXXXXXXXX X 0 0 0 X X 0X 0 X 0 X X 0 0 X X XXX 0X X XXXX X XFX0 0 0 XX X X 0 X0X X X X 0 0 0 0 X XXXX XXXXXXXXX X X X X X######X X######X X######X XXXXXXXX ', /*9*/' XXXXXXX X ###X XXXXX ###X X # #X X XX ###X XX XX ###X XXX XXXXXXXX X 000 XX XXXXX 0 0 XXXXX XX X0 0 X X XF 0 0 0 0 X XXXXXX 00 0 XXXXX X X XXXXXXXX ', /*10*/' XXX XXXXXXXXXXXXXXXFXXXX X XX 00 00 0 0 ###XX 000X 0 X###XX 0 X 00 00 X###XXXX X 0 X###XX X 0 0 0 X###XX XXXXXX XXX###XXX X X 0 0 X###XX XX X 00 0 0XX##XX ##X X 0 X#XX ##X X 000 000 X#XXXXXX X X X#X X XXXXXXXXX X#X X X#X XXXXXXXXXXXXXXX', /*11*/' XXXX XXXX X X XXX XXX0 X XX F 0 X XX 0 00XX XX X X0XX X X X 0 00 X XXX X 0 X X 0 XXXXXXXXX X 00 X XXXXX XX 0 XX# XXX XXXXXXXXX## ##X XXXX X###X#X X#####X XXXXXXX ', /*12*/' XXXXXXXXXXXXXXXX X X X X XXXXXX X X X 0 0 0 0X X X X 0F0 XX XX X X X0 0 0XXX###X X X 0 0 XX###X X XXX000 0 XX###X X X XX XX###X XXXXX XX XX###X XXXXX XXX X X XXXXXXX ', /*13*/' XXXXXXXXX XX XX XXXXX XXX X X XXXX 0 X0 X X ### XX X 0XF0XX X X#X# XX X X0 X # # XX 0 0 X X X#X# XX XX XX0 0 # # XX 0 X X X0X#X# XXX 0 0 0 0### X X0 XXXXXX XX X X X XXXXXXXXXX XXXX ', /*14*/' XXXXXXX XXXXXXX X X X 0F0 X X00 X XXXXXXXXX X XXX######XX X X 0######XX X X X XXX###### X XX XXXX XXX X0XX X X0 X 0 X X X 0 000 X 0XX X X 0 0 XXX00 X X XXXXX 0 X X XXX XXX X X X X X XXXXXXXX X XXXX ', /*15*/' XXXXXXX X X X X 0 X XXX X0 XXXX X 0 XX0 X X X F 0 X 0X X X 0 XXXX XX XXXX0XX X X 0X#####X X X X 0##11# 0X XXX XX X#####X X X XXX XXXXXXX X 00 X X X X X XXXXXX X XXXXX ', /*16*/' XXXXX X XX X X XXXX X 0 XXXX X X 00 0 0X XXXF X0 XX X XX 0 0 XX X 0 XX XX #X X X0XX0 X#X XXX 0##XX#X X X#1###X X 00 X#####X X XXXXXXXXX X X XXXX ', /*17*/' XXXXXXXXXX X## X X X## X X## X XXXX XXXXXXX X XX X X X X XX X X XXXX XX XXXX XX X 0 XXXXX X X X X 0 0 X 0 X X F0 0 X XX XXXX XX XXXXXXX X X XXXXXX ', /*18*/' XXXXXXXXXXX X # X X X X# F X XXXXX XX##X XXXX XX X ##XXX XXXX 0 X### 0 X 0 XX ## XX XX XX XXXXX0XX0X 0 X X X XX X X0 00 X X X 0 X X X 0XX X X X X XXXXXXXXXXX X XXXX XXXX ', /*19*/' XXXXXX X FXXXX XXXXX 0 X X XX XXXX X 0 X XX X X 0 X XXXXX X XX 0 0 X X XX 0 0 XXX X X XX X 0 X X X XX X X0X X X XX XXX X X XXXXXXX 0 XXXX X X####XX 0 0 ##X#XXXXX0 0X 0 ####XX X XX ####XXXXXXXXXXXXXXXXXXXX', /*20*/' XXXXXXXXXX XXXXX XXXX X X 0 XF X X XXXXXXX0XXXX XXXX X XX X X0 ##XX X 0 0 X X X#XX X 0 X X0 ##XX X XXX XX X#XX XXX X X X0 ##XX X X 0XXXX X#XX X0 0 0 X1 ##XX 0 X 0 0 X X#XXXXX 0XXX X1 ##X X 00 XXX####X X XX XXXXXX XXXXXXXX ', /*21*/' XXXXXXXXX X X X XXXX XX XXXX X X XX XFXX X X 000 0 00X X X XX 0 X X X XX 0 XXXX XXXX 000 0X X X XX ####X X X X X## #X X X X XX###X XXXXX 0 X###X XX XXXXX XXXXX ', /*22*/'XXXXX XXXX X XXXXXXX XXXXXX 0X X 0 X XX 0 0 0 X 0 0 XXX0 0 X FX 0 XX 0 XXXXXXXXXXX XXX X X#######X 0X X XX X ######X X X X 0########0 X X X 0 X#### ##X X X 0 0XXXX0XXXX 0X X 0 XXX 0 0 XXX 0 0 0 0 XXX XXXXXX 0 XXXXX XX X XXXXXXXXXXXXXXXXXXXX', /*23*/' XXXXXXX X X XXXX XXXXX 0X0 X XX X## X X X X X## X 0X0 X 0XXXX X# X X0 X X X## 0X X 0 X X##FX X0 X0 X X X## X 0X 0X X X## X X00X0 X XXX## X 0X X 0X0 XX## X X X X XXX# XXXX XXXXX X XXXX XXXX XXXXX ', /*24*/'XXXXXXXXXXXXXXX X########## #XXXX X##########00#X X XXXXXXXXXXX0 X XXX 0 0 0 XXX XXXX X 0 X XX X XX X XXX 0X X XX XXX XXX 0 X0XXX XXX XXXXX 0 X X XXX XXXXX 0 XX X X XX X 0 X 0 0 0 X X 0 0X000 X X X X 0 XXXXX X FXX X X X XXXXXXXXXXXXXX ', /*25*/'XXXX X XXXXXXXXXXXXXX X X ##X######X X X X XXXXX ###X XX0X ########X X XX0XXXXXX XXXXX 0 X XXXXXXF XXX0 X 0 XXXXXX XX 0 X000XX XX X X0X0XXXX XXXX X00000 X X X 0 X X X X XX XX XXXX XXXXXX0XXXXXX 0 XX X X XXXXXXXXXXX XXXXX', /*26*/' XXXXXXX X X XXXXX XX X X###XXX X 0X X### X X 0 X00 ### X X 0X X### #X X X 0XXXXXXXX XX0 0 0 X XX X 00 X X XXXXXX XX00FX X XX XXXXXXXX ', /*27*/' XXXXXXXXXXXXXXXXX X### X X XXXX##### 0XX X X0 XX######X 0 X XX######X X X X XXXXXXXXXX 0 0 0 X X X0XX0 XX0XX XX 0 X 0 X X XX XXX X XX0 X X 0 00 0 0 X X 0 0XX0 XXXXXX XXXXXXX F XX XXXXXX ', /*28*/' XXXXX XXXXX X XX 0 0 XXXX XXXXX 0 0 0 XX#X X 00 XX##X X XXXXXX XXX## X XX X X X### X X 0 X X### X XF X0 XX XXXX###X XXXX 0 00 XX##X XX 0 0 0###X X 00 0 X #X X 0 0 XXXX XXXXXX X XXXXX ', /*29*/' XXXXX X XX X 0 XXXXXXXXX XX X X XXXXXXXX X 0X0XF X XX X 0 X 0 XX XXX XXXXXXXXX XXX XX ##1##### X XXXX XX 1#1##1#1 X XXX 0XXXXXXXXXX XX0 XX 0 0 0 0 XX X X X X XXXXXXXXXXXXXXXXXXXX ', /*30*/' XXXXXXXXXXX X X X XXXXX X 0 0 X X XXXXX 0XX X XX X 0 XX X XX 0 X X 0 F00 X XX000 X XX XXX X XX X XX X XXX XXXXX0X XX X 0 X####X X XXX XX 0 X####XXX 0 0 X X##0# XX XX 0 X XX#### XXXXXX XXXXXX###XX XXXXX XXXXX ', /*31*/' XXXX X XXXXXXXXX XX XX X X X 0X 0F0 XXXX X0 0 X 0 0X XX XX 0XX X0 0 X X X X X 000 X X 0 0 0XX XXXX X 0 0 X0X X X XX XXX XXX0 X X X#### X XXXX######XXXX X####XXXX X###XX X###X XXXXX ', /*32*/' XXXX XXXXX X XX 0X XX 0 XX XXX XF0 0 X 0 X XXXX XX 0X X####X0 0 X X####X 0X X#### 00 XX X### X 0 X XXXXXX0 0 X X XXX X0 XXX X X XXXX ', /*33*/' XXXXXXXXXXXX XX XX X XX 0 0 X XXXX XX 00 X X 0 X X X 000 X XXXX X X X 0 XX X X X 0 X X 0X 0X X X ##X XXXX XXXX## 0 XFX X#####X 0X X XX####X 0 X XXX##XX X XXXXXXXXXXXX ', /*34*/' XXXXXXXXX X#### XX X#X#X 0 XX XX####X X FXX X ####X X XX X X0 XX0 X XX XXX 0 X X0 0 0 0X X X X 0 0 XX X X XXX XX X X XX XX XX X 0 X 0 X XXX0 0 XXX X XXXXX XXXX ', /*35*/'XXXXXXXXXXXX XXXXXXX X X XXX####XX 00X F #####XX X XXX X ####XXX XX XXX X ####X X 0 0 X X XXXX X 0 0XX X XXXXX X XXXX X XX XX X X0 XX X XX 0 0 X XX X XXX X 0 0 X X X X 0 XX XX X XXXXX X 00 00 X XX XX XXX 0 X X X X X XXXXXX XXXXXX ', /*36*/' XXXXX XXXXX XXXXXX X X XXXX 0 0 0 X X 0 XX XX XX XX X 0 0 0 0 X XXX 0 XX XX XX X XXXXX XXXXX00 X XX0XXXXX FXX X X 0 XXX0XXX 0 XX X 0 X XXX XXX X 00 0 X 00 X X X XX X XXXXXXX## #XXX X#########X X#########X XXXXXXXXXXX ', /*37*/'XXXXXXXXXXX X###### XXXXXXXXXX###### X XX XX##XXX 0 0 XX### 0 0 X XXX XX###X0XXXXX X XXXX X X0 X0 X X 00 0 0 0XX X X 0 X0X0 XX0 X XXX XX X XX X X 0 0 XX XXXXXX X 0 0 X XX X X X XXXXXFXXXXX XXX ', /*38*/' XXXX XXXXXXX FX X 0 X X 0XX 0X XX0X###X X X 0### X X X# #X XX X X X0 X X0 0 X X XXXXXXX XXXX ', /*39*/' XXXXXX XXXXXXXXXXXXX####XXX XX XX####XX 00XX 0 FXX####XX 00 0X ####XX 0 XX 00 X X ###XX 0 XX 0 X ####XXX XXXXX XXX XX#XXXXX 0 0 XX # XX 0XXX X XXXXX XXXX 0 X X X 0 X0 0 0XXX X X 000X 0 X XXXX X X 00 X XXXXXX XXX XXXXX ', /*40*/' XXXXXXXXXXXX X XX X X X00 0 X X0 X0X XX FX XX XX X 0 X XX X 0 X0 X X X X 0 X X XX 0 0 XX X X X XX 0 X X XX 00X X XXXXXX00 X X X####X XXXXXXXX X#X### XX X#### X X#### X XXXXXXXXX ', /*41*/' XXXXX XX XX XX X XX 00 X XX 00 0 X X 0 0 X XXXX X 00 XXXXXX XXXXXXXX XX XX# 000FXX#X XXXXXXX XX XXX#X XXXXXXX# X0 0XXX########### X XXXXXXXXXXXXXXX 0 X XX XX XXXX ', /*42*/' XXXXXXXX XXXX XXXXXX X XX 0 0 FX X XX XX0X0 0 0XX XXX ######X 00 XX X ######X X X X X ######X0 0 X X X ###### 00X 0 X X 0XXX XXX0 0 XX XXX 0 0 0 0 X X 0 0 0 0 X XXXXXX XXXXXX XXXXX ', /*43*/' XXXXXXX XXXXX X XXXX X X 0 X XXXX X00 XX XX X XX X X XX XXXX XXX 0X0 0 0 XX### X XX X XX###X F X XXX XXX###X XXX 0 0 XXXXXXXXX XX X X XXXXXXXXX ', /*44*/' XXXXX X X X X XXXXXXX X 0FXXXXXX X 0 XX0 XXX X X XXXX 0 0 X X XXXXX X X0 XXXXXX XXXX XX0 XX 0X 0 X XX XX XX X X###X XXXXXXX XXX ### X XXXX X X###X X X XXX X X X X XXXXXXXXX', /*45*/' XXXXX XXXX X###X X XXXX X###XXX 0 X X####XX 0 0XXX XX####XX 0 X XXX### XX 0 0 X X XX X 0 X X XX X XXX XXXX X 0 X X0 0 X X 0 F 0 0 X X X 0 00 0 XXX X XXXXXX XXX X XX XXXX XXX ', /*46*/' XXXXXXXXXX X XXXX X XXXXXX X XX X X 0 0 0 0 X X X0 X XXX0 00X XXX X XX X 0XX XX0X 0 FX X 0 0 XXX X X 0 X X XX X X XX XXXXX X X X X#######XXX X#######X XXXXXXXXX ', /*47*/' XXXX XXXXXXXXX XX XX 0 0 XXXXX X XX XX XX###X X X00 0 00X0XX###X X X F X ###X X 0X XXX00 ###X X 0 00 0 XX####X XXX0 XXXXXXX X XXXXXXX XXXX ', /*48*/' XXXXXXXXX X1#1X1#1X X#1#1#1#X X1#1#1#1X X#1#1#1#X X1#1#1#1X XXX XXX X X XXXXXX XXXXXX X X X 0 0 0 0 0 X XX 0 0 0 0 XX X0 0 0 0 0X X 0F0 X X XXXXX X XXXX XXXX ', /*49*/' XXXX X XX X XX X 00 XX XXX0 0 XX XXXX 0 X XXX X XXXXX X X X X####0 X X X 0 ####X X X 0 X X#1##X X XXX XXXX XXX X XXXX F0 XX0XX XXX 0 X X XX X XXXXXXXXX ', /*50*/' XXXXXXXXXXXX XX## X X XX##1 0 0 X XX##1#X X X0 XX X##1#X X X 0 X XXXX###X X X X X XX X X X F0 0 XXX X X XX X 0 0 X X X XXX00 X X X X X X 0 X X XXXXX X 0X XXXXX X X0 X X X X X XXX XX X X X X XX XXXX XXXXXX ' ]; var sb = null; function load_map(n) { sb = new Sokoban(); sb.grid_width = 19; sb.grid_height = 16; if (n == -1) { sb.grid_width = 26; sb.grid_height = 16; sb.grid_code = '' + ' ' + 'XXXXXXX ' + ' X X ' + ' X X ' + ' X XXXX XXXX XXXXX ' + ' X X X X X X ' + ' X XXXXXX XX X ' + ' X X XX X ' + ' X X X X X X X' + ' X XXXX XXXX XX ' + ' ' + ':::::::::XXXXXXXX:::::::::' + '::::::::X X:::::::::' + '::::::::X F 0 # X:::::::::' + '::::::::X X:::::::::' + ':::::::::XXXXXXX::::::::::'; } else { sb.grid_code = sb_maps[n]; } sb.render_grid(); $('map').innerHTML = lpad(n + 1, 2); } function sokoban_move(e) { var keynum; if (sb == null) { return true; } if (window.event) { keynum = e.keyCode; } else if (e.which) { keynum = e.which; } if (keynum == 85) { sb.undo_move(); return false; } if (keynum == 37 || keynum == 100 || keynum == 65) { sb.validate_move(SD_LEFT); return false; } if (keynum == 39 || keynum == 102 || keynum == 68) { sb.validate_move(SD_RIGHT); return false; } if (keynum == 38 || keynum == 104 || keynum == 87) { sb.validate_move(SD_FORWARD); return false; } if (keynum == 40 || keynum == 98 || keynum == 83) { sb.validate_move(SD_BACKWARD); return false; } return true; }