commit 4e9eb1c2b7b79ca5257a83ab9a99540235a4e65d
parent 38a4ae74c13cb23bb1ce8b4f7c9f8bc8f89e3a55
Author: Yuval Langer <yuvallangerontheroad@gmail.com>
Date: Mon, 6 Jul 2020 17:45:04 +0300
Add win state and continue button.
Diffstat:
M | html/sokoban.html | | | 40 | +++++++++++++++++++++++++++------------- |
M | html/sokoban.js | | | 192 | ++++++++++++++++++++++++++++++++++++++++++++----------------------------------- |
2 files changed, 133 insertions(+), 99 deletions(-)
diff --git a/html/sokoban.html b/html/sokoban.html
@@ -4,27 +4,39 @@
<meta charset="utf-8">
<title>Kaka Farm's Sokoban clone: no bells no whistles no glory.</title>
<link href="sokoban.css" rel="stylesheet"></style>
+ <script type="text/javascript">
+'use strict';
+
+
+window.kakalog_activated = true;
+ </script>
+ <script type="text/javascript" src="kakalog.js"></script>
<script type="text/javascript" src="sokoban.js"></script>
<script type="text/javascript">
'use strict';
+
(function() {
function main() {
- let state = sokoban.read_level_text(sokoban.level1);
- let text_element = document.querySelector('#text');
- text_element.innerText = sokoban.state_to_text(state);
+ let game = sokoban.load_game();
+ let text_element = document.getElementById('text');
+ text_element.innerText = sokoban.game_to_text(game);
[
- ['#up', [0, -1]],
- ['#down', [0, 1]],
- ['#left', [-1, 0]],
- ['#right', [1, 0]],
- ].forEach(([id, direction])=>{
- let button = document.querySelector(id);
- button.addEventListener('click', function() {
- sokoban.step(state, direction);
- text_element.innerText = sokoban.state_to_text(state);
- });
+ ['up', sokoban.action_step_up],
+ ['down', sokoban.action_step_down],
+ ['left', sokoban.action_step_left],
+ ['right', sokoban.action_step_right],
+ ['next_level', sokoban.action_next_level],
+ ].forEach(([element_id, action_function])=>{
+ let button = document.getElementById(element_id);
+ console.debug(button)
+ function click_handler() {
+ console.debug('click: ' + element_id);
+ action_function(game);
+ text_element.innerText = sokoban.game_to_text(game);
+ };
+ button.addEventListener('click', click_handler);
});
};
@@ -38,5 +50,7 @@
<button id="down" type="button">↓</button>
<button id="left" type="button">←</button>
<button id="right" type="button">→</button>
+ <button id="next_level" type="button">c</button>
+ <pre id="log"></pre>
</body>
</html>
diff --git a/html/sokoban.js b/html/sokoban.js
@@ -1,11 +1,17 @@
'use strict';
-console.log('a');
+console.log('sokoban.js start.');
let sokoban = (function() {
- let level1 = `
+ let levels = [
+ `
+##############
+#.@...*....z.#
+##############
+`,
+ `
#####
#...#
#*..#
@@ -17,7 +23,8 @@ let sokoban = (function() {
#####.###.#@##..zz#
#.....#########
#######
-`;
+`,
+ ];
let level_win_test_not_all_endings = `
#####
#...#
@@ -53,12 +60,12 @@ let sokoban = (function() {
endings: [],
};
let lines = s.split('\n');
- let max_x = Math.max(...lines.map(line=>line.length))
+ let max_x = Math.max(...lines.map(line=>line.length));
for (let y = 0; y < lines.length; y++) {
- state.walls[y] = []
- state.rocks[y] = []
- state.floors[y] = []
- state.endings[y] = []
+ state.walls[y] = [];
+ state.rocks[y] = [];
+ state.floors[y] = [];
+ state.endings[y] = [];
for (let x = 0; x < lines[y].length; x++) {
if (lines[y][x] == '@') {
state.position = [x, y];
@@ -98,48 +105,18 @@ let sokoban = (function() {
return state.floors[y][x] == '.';
}
function move_rock(state, [fx, fy], [tx, ty]) {
- console.log(fx, fy, tx, ty);
delete state.rocks[fy][fx];
state.rocks[ty][tx] = '*';
}
- function step(state, direction) {
- let p0 = state.position;
- let p1 = [
- p0[0] + direction[0],
- p0[1] + direction[1]];
- let p2 = [
- p1[0] + direction[0],
- p1[1] + direction[1]];
-
- console.log(p0, p1, p2)
-
- let is_walking = here_floor(state, p1);
- let is_blocked = (
- here_wall(state, p1) || (
- here_rock(state, p1) && (
- here_rock(state, p2) ||
- here_wall(state, p2))));
- let is_pushing = (
- here_rock(state, p1) &&
- !here_rock(state, p2));
-
- console.log(is_walking, is_blocked, is_pushing);
-
- if (!is_blocked) {
- if (is_pushing) {
- move_rock(state, p1, p2);
- };
- state.position = p1;
- };
- };
-
- function is_win(state) {
- for (let y = 0; y < state.rocks.length; y++) {
- for (let x = 0; x < state.rocks[y].length; x++) {
- if (here_rock(state, [x, y]) != here_ending(state, [x, y])) {
- return false;
+ function is_won(game) {
+ for (let y = 0; y < game.level_state.rocks.length; y++) {
+ if (game.level_state.rocks[y] != undefined) {
+ for (let x = 0; x < game.level_state.rocks[y].length; x++) {
+ if (here_rock(game.level_state, [x, y]) != here_ending(game.level_state, [x, y])) {
+ return false;
+ }
}
}
}
@@ -147,33 +124,82 @@ let sokoban = (function() {
};
- function state_to_text(state) {
+ function action_step(game, direction) {
+ if (!is_won(game)) {
+ let p0 = game.level_state.position;
+ let p1 = [
+ p0[0] + direction[0],
+ p0[1] + direction[1]];
+ let p2 = [
+ p1[0] + direction[0],
+ p1[1] + direction[1]];
+
+ let is_walking = here_floor(game.level_state, p1);
+ let is_blocked = (
+ here_wall(game.level_state, p1) || (
+ here_rock(game.level_state, p1) && (
+ here_rock(game.level_state, p2) ||
+ here_wall(game.level_state, p2))));
+ let is_pushing = (
+ here_rock(game.level_state, p1) &&
+ !here_rock(game.level_state, p2));
+
+ if (!is_blocked) {
+ if (is_pushing) {
+ move_rock(game.level_state, p1, p2);
+ };
+ game.level_state.position = p1;
+ };
+ };
+ };
+
+ function action_step_up(game) { action_step(game, [0, -1]); };
+ function action_step_down(game) { action_step(game, [0, 1]); };
+ function action_step_left(game) { action_step(game, [-1, 0]); };
+ function action_step_right(game) { action_step(game, [1, 0]); };
+
+
+ function action_next_level(game) {
+ if (is_won(game) && game.current_level_number < levels.length) {
+ game.current_level_number += 1;
+ game.level_state = read_level_text(levels[game.current_level_number]);
+ };
+ };
+
+
+ function game_to_text(game) {
let s = '';
+
+ if (is_won(game)) {
+ s = s.concat('Won! Press c to continue.');
+ }
+ s = s.concat(`Level ${game.current_level_number + 1}`);
+
let max_y = Math.max(
- state.rocks.length,
- state.endings.length,
- state.floors.length,
- state.walls.length,
- state.position[1],
+ game.level_state.rocks.length,
+ game.level_state.endings.length,
+ game.level_state.floors.length,
+ game.level_state.walls.length,
+ game.level_state.position[1],
);
for (let y = 0; y < max_y; y++) {
let max_x = Math.max(
- state.rocks[y].length,
- state.endings[y].length,
- state.floors[y].length,
- state.walls[y].length,
- state.position[0],
+ game.level_state.rocks[y].length,
+ game.level_state.endings[y].length,
+ game.level_state.floors[y].length,
+ game.level_state.walls[y].length,
+ game.level_state.position[0],
);
for (let x = 0; x < max_x; x++) {
- if (here_player(state, [x, y])) {
+ if (here_player(game.level_state, [x, y])) {
s = s.concat('@');
- } else if (here_wall(state, [x, y])) {
+ } else if (here_wall(game.level_state, [x, y])) {
s = s.concat('#');
- } else if (here_rock(state, [x, y])) {
+ } else if (here_rock(game.level_state, [x, y])) {
s = s.concat('*');
- } else if (here_floor(state, [x, y])) {
+ } else if (here_floor(game.level_state, [x, y])) {
s = s.concat('.');
- } else if (here_ending(state, [x, y])) {
+ } else if (here_ending(game.level_state, [x, y])) {
s = s.concat('z');
} else {
s = s.concat(' ');
@@ -182,35 +208,29 @@ let sokoban = (function() {
s = s.concat('\n');
};
- return s;
+ return s.trimEnd();
};
- let state = read_level_text(level1);
- [
- [0, -1],
- [-1, 0],
- [-1, 0],
- [-1, 0],
- [-1, 0],
- [-1, 0],
- [-1, 0],
- [-1, 0],
- [-1, 0],
- [-1, 0],
- ].forEach(
- direction=>{
- step(state, direction);
- console.log(state_to_text(state));
- console.log(is_win(state));
- }
- );
+
+ function load_game() {
+ let game = {
+ level_state: read_level_text(levels[0]),
+ current_level_number: 0,
+ };
+ return game;
+ };
return {
- step,
- is_win,
- level1,
- read_level_text,
- state_to_text,
+ action_next_level,
+ action_step_down,
+ action_step_left,
+ action_step_right,
+ action_step_up,
+ game_to_text,
+ load_game,
};
})();
+
+
+console.log('sokoban.js end.');