kaka.farm

Unnamed repository; edit this file 'description' to name the repository.
git clone https://kaka.farm/~git/kaka.farm
Log | Files | Refs | README

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:
Mhtml/sokoban.html | 40+++++++++++++++++++++++++++-------------
Mhtml/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.');