File indexing completed on 2024-05-05 15:53:13
0001 /* GCompris - maze.js 0002 * 0003 * SPDX-FileCopyrightText: 2014 Stephane Mankowski <stephane@mankowski.fr> 0004 * 0005 * Authors: 0006 * Bastiaan Verhoef <b.f.verhoef@student.utwente.nl> (GTK+ version) 0007 * Stephane Mankowski <stephane@mankowski.fr> (Qt Quick port) 0008 * 0009 * SPDX-License-Identifier: GPL-3.0-or-later 0010 */ 0011 .import "qrc:/gcompris/src/core/core.js" as Core 0012 0013 var url = "qrc:/gcompris/src/activities/maze/resource/" 0014 var numberOfLevel = 25 0015 var items 0016 var relativeMode 0017 var invisibleMode 0018 0019 var NORTH = 1 0020 var WEST = 2 0021 var SOUTH = 4 0022 var EAST = 8 0023 var SET = 16 0024 0025 var mazeColumns = 0 0026 var mazeRows = 0 0027 var maze = 0 0028 0029 var win = false 0030 0031 function start(items_, relativeMode_, invisibleMode_) { 0032 items = items_ 0033 relativeMode = relativeMode_ 0034 invisibleMode = invisibleMode_ 0035 items.currentLevel = Core.getInitialLevel(numberOfLevel) 0036 initLevel() 0037 } 0038 0039 function stop() {} 0040 0041 function initLevel() { 0042 items.wallVisible = !invisibleMode 0043 0044 win = false 0045 0046 /* Set main variables */ 0047 if (items.currentLevel + 1 == 1) { 0048 mazeColumns = 4 0049 mazeRows = 4 0050 } else if (items.currentLevel + 1 == 2) { 0051 mazeColumns = 5 0052 mazeRows = 4 0053 } else if (items.currentLevel + 1 == 3) { 0054 mazeColumns = 5 0055 mazeRows = 5 0056 } else if (items.currentLevel + 1 == 4) { 0057 mazeColumns = 6 0058 mazeRows = 5 0059 } else if (items.currentLevel + 1 == 5) { 0060 mazeColumns = 6 0061 mazeRows = 6 0062 } else if (items.currentLevel + 1 == 6) { 0063 mazeColumns = 6 0064 mazeRows = 7 0065 } else if (items.currentLevel + 1 == 7) { 0066 mazeColumns = 7 0067 mazeRows = 7 0068 } else if (items.currentLevel + 1 == 8) { 0069 mazeColumns = 8 0070 mazeRows = 7 0071 } else if (items.currentLevel + 1 == 9) { 0072 mazeColumns = 8 0073 mazeRows = 8 0074 } else if (items.currentLevel + 1 == 10) { 0075 mazeColumns = 9 0076 mazeRows = 8 0077 } else if (items.currentLevel + 1 == 11) { 0078 mazeColumns = 9 0079 mazeRows = 9 0080 } else if (items.currentLevel + 1 == 12) { 0081 mazeColumns = 10 0082 mazeRows = 9 0083 } else if (items.currentLevel + 1 == 13) { 0084 mazeColumns = 10 0085 mazeRows = 10 0086 } else if (items.currentLevel + 1 == 14) { 0087 mazeColumns = 8 0088 mazeRows = 16 0089 } else if (items.currentLevel + 1 == 15) { 0090 mazeColumns = 14 0091 mazeRows = 14 0092 } else if (items.currentLevel + 1 == 16) { 0093 mazeColumns = 16 0094 mazeRows = 15 0095 } else if (items.currentLevel + 1 == 17) { 0096 mazeColumns = 17 0097 mazeRows = 16 0098 } else if (items.currentLevel + 1 == 18) { 0099 mazeColumns = 18 0100 } else if (items.currentLevel + 1 == 19) { 0101 mazeColumns = 19 0102 mazeRows = 18 0103 } else if (items.currentLevel + 1 == 20) { 0104 mazeColumns = 19 0105 mazeRows = 19 0106 } else if (items.currentLevel + 1 == 21) { 0107 mazeColumns = 20 0108 mazeRows = 19 0109 } else if (items.currentLevel + 1 == 22) { 0110 mazeColumns = 20 0111 mazeRows = 20 0112 } else if (items.currentLevel + 1 == 23) { 0113 mazeColumns = 19 0114 mazeRows = 21 0115 } else if (items.currentLevel + 1 == 24) { 0116 mazeColumns = 23 0117 mazeRows = 21 0118 } else if (items.currentLevel + 1 == 25) { 0119 mazeColumns = 23 0120 mazeRows = 23 0121 } 0122 0123 items.mazeRows = mazeRows 0124 items.mazeColumns = mazeColumns 0125 0126 /* Build maze */ 0127 maze = [] 0128 for (var id = 0; id < mazeColumns * mazeRows; ++id) { 0129 maze[id] = 15 0130 } 0131 0132 /* Generate maze */ 0133 generateMaze(Math.floor(Math.random() * mazeColumns), 0134 Math.floor(Math.random() * mazeRows)) 0135 0136 /* Remove set */ 0137 for (id = 0; id < mazeColumns * mazeRows; ++id) { 0138 maze[id] = maze[id] ^ SET 0139 } 0140 0141 /* Set maze */ 0142 items.mazeRepeater = maze 0143 0144 /* Set initial position of player */ 0145 items.playerx = 0 0146 items.playery = Math.floor(Math.random() * mazeRows) 0147 0148 /* Set position of door */ 0149 items.doory = Math.floor(Math.random() * mazeRows) 0150 0151 items.fastMode = (items.currentLevel + 1 >= 14) 0152 } 0153 0154 function getId(x, y) { 0155 return x + y * mazeColumns 0156 } 0157 0158 function check(x, y) { 0159 if (maze[getId(x, y)] & SET) 0160 return 1 0161 return 0 0162 } 0163 0164 function isPossible(x, y) { 0165 var wall = maze[getId(x, y)] 0166 var pos = [] 0167 wall = wall ^ SET 0168 pos[0] = 0 0169 if (x === 0) { 0170 wall = wall ^ WEST 0171 } 0172 if (y === 0) { 0173 wall = wall ^ NORTH 0174 } 0175 if (x === mazeColumns - 1) { 0176 wall = wall ^ EAST 0177 } 0178 if (y === mazeRows - 1) { 0179 wall = wall ^ SOUTH 0180 } 0181 if (wall & EAST) { 0182 if (check(x + 1, y) === 0) { 0183 pos[0] = pos[0] + 1 0184 pos[pos[0]] = EAST 0185 } 0186 } 0187 if (wall & SOUTH) { 0188 if (check(x, y + 1) === 0) { 0189 pos[0] = pos[0] + 1 0190 pos[pos[0]] = SOUTH 0191 } 0192 } 0193 if (wall & WEST) { 0194 if (check(x - 1, y) === 0) { 0195 pos[0] = pos[0] + 1 0196 pos[pos[0]] = WEST 0197 } 0198 } 0199 if (wall & NORTH) { 0200 if (check(x, y - 1) === 0) { 0201 pos[0] = pos[0] + 1 0202 pos[pos[0]] = NORTH 0203 } 0204 } 0205 return pos 0206 } 0207 0208 function generateMaze(x, y) { 0209 maze[getId(x, y)] = maze[getId(x, y)] + SET 0210 var po = isPossible(x, y) 0211 while (po[0] > 0) { 0212 var ran = po[Math.floor(Math.random() * po[0]) + 1] 0213 switch (ran) { 0214 case EAST: 0215 maze[getId(x, y)] = maze[getId(x, y)] ^ EAST 0216 maze[getId(x + 1, y)] = maze[getId(x + 1, y)] ^ WEST 0217 generateMaze(x + 1, y) 0218 break 0219 case SOUTH: 0220 maze[getId(x, y)] = maze[getId(x, y)] ^ SOUTH 0221 maze[getId(x, y + 1)] = maze[getId(x, y + 1)] ^ NORTH 0222 generateMaze(x, y + 1) 0223 break 0224 case WEST: 0225 maze[getId(x, y)] = maze[getId(x, y)] ^ WEST 0226 maze[getId(x - 1, y)] = maze[getId(x - 1, y)] ^ EAST 0227 generateMaze(x - 1, y) 0228 break 0229 case NORTH: 0230 maze[getId(x, y)] = maze[getId(x, y)] ^ NORTH 0231 maze[getId(x, y - 1)] = maze[getId(x, y - 1)] ^ SOUTH 0232 generateMaze(x, y - 1) 0233 break 0234 } 0235 po = isPossible(x, y) 0236 } 0237 } 0238 0239 function nextLevel() { 0240 items.currentLevel = Core.getNextLevel(items.currentLevel, numberOfLevel); 0241 initLevel(); 0242 } 0243 0244 function previousLevel() { 0245 items.currentLevel = Core.getPreviousLevel(items.currentLevel, numberOfLevel); 0246 initLevel(); 0247 } 0248 0249 function getMaze() { 0250 return maze 0251 } 0252 0253 function autoMove() { 0254 if (items && items.fastMode) { 0255 var number = 0 0256 var result = 0 0257 if (getPlayerRotation() !== 90 && !(maze[getId( 0258 items.playerx, 0259 items.playery)] & EAST)) { 0260 number++ 0261 result |= EAST 0262 } 0263 if (getPlayerRotation() !== 270 && !(maze[getId( 0264 items.playerx, 0265 items.playery)] & WEST)) { 0266 number++ 0267 result |= WEST 0268 } 0269 if (getPlayerRotation() !== 180 0270 && !(maze[getId(items.playerx, items.playery)] & SOUTH)) { 0271 number++ 0272 result |= SOUTH 0273 } 0274 if (getPlayerRotation() !== 0 && !(maze[getId( 0275 items.playerx, 0276 items.playery)] & NORTH)) { 0277 number++ 0278 result |= NORTH 0279 } 0280 if (number == 1) { 0281 if (items.playery !== items.doory 0282 || items.playerx !== mazeColumns - 1) { 0283 switch (result) { 0284 case EAST: 0285 items.playerr = 270 0286 ++items.playerx 0287 break 0288 case WEST: 0289 items.playerr = 90 0290 --items.playerx 0291 break 0292 case NORTH: 0293 items.playerr = 180 0294 --items.playery 0295 break 0296 case SOUTH: 0297 items.playerr = 0 0298 ++items.playery 0299 break 0300 } 0301 0302 /* Check if success */ 0303 checkSuccess() 0304 } 0305 } 0306 } 0307 } 0308 0309 /* 0= SOUTH 0310 * 90= WEST 0311 * 180 = NORTH 0312 * 270 =EST 0313 */ 0314 function getPlayerRotation() { 0315 return ((items.playerr % 360) + 360) % 360 0316 } 0317 0318 function checkSuccess() { 0319 if (items.playery === items.doory && items.playerx === mazeColumns - 1) { 0320 win = true 0321 items.bonus.good("lion") 0322 } 0323 } 0324 0325 function processPressedKey(event) { 0326 /* Mode invisible */ 0327 if (invisibleMode && event.key === Qt.Key_Space) { 0328 items.wallVisible = !items.wallVisible 0329 items.message.visible = items.wallVisible 0330 } 0331 0332 if ( !win ) { 0333 /* Move the player */ 0334 switch (event.key) { 0335 case Qt.Key_Right: 0336 clickRight() 0337 event.accepted = true 0338 break 0339 case Qt.Key_Left: 0340 clickLeft() 0341 event.accepted = true 0342 break 0343 case Qt.Key_Up: 0344 clickUp() 0345 event.accepted = true 0346 break 0347 case Qt.Key_Down: 0348 clickDown() 0349 event.accepted = true 0350 break 0351 } 0352 } 0353 } 0354 0355 function clickRight() { 0356 /* Move the player */ 0357 if ((!invisibleMode || !items.wallVisible) 0358 && (items.playery !== items.doory 0359 || items.playerx !== mazeColumns - 1)) { 0360 if (relativeMode) { 0361 /* Relative mode */ 0362 if (items.playerr % 90 === 0) 0363 items.playerr += 90 0364 } else { 0365 /* Absolute mode */ 0366 var curpos = getPlayerRotation() 0367 items.playerr = items.playerr - (curpos === 0 ? 90 : curpos - 270) 0368 if (!(maze[getId(items.playerx, items.playery)] & EAST)) { 0369 ++items.playerx 0370 } else { 0371 items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/brick.wav") 0372 } 0373 } 0374 } 0375 0376 /* Check if success */ 0377 checkSuccess() 0378 } 0379 0380 function clickLeft() { 0381 /* Move the player */ 0382 if ((!invisibleMode || !items.wallVisible) 0383 && (items.playery !== items.doory 0384 || items.playerx !== mazeColumns - 1)) { 0385 if (relativeMode) { 0386 /* Relative mode */ 0387 if (items.playerr % 90 === 0) 0388 items.playerr -= 90 0389 } else { 0390 /* Absolute mode */ 0391 var curpos = getPlayerRotation() 0392 items.playerr = items.playerr - curpos + 90 0393 if (!(maze[getId(items.playerx, items.playery)] & WEST)) { 0394 --items.playerx 0395 } else { 0396 items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/brick.wav") 0397 } 0398 } 0399 } 0400 0401 /* Check if success */ 0402 checkSuccess() 0403 } 0404 0405 function clickDown() { 0406 /* Move the player */ 0407 if ((!invisibleMode || !items.wallVisible) 0408 && (items.playery !== items.doory 0409 || items.playerx !== mazeColumns - 1)) { 0410 if (relativeMode) { 0411 /* Relative mode */ 0412 if (items.playerr % 90 === 0) { 0413 if (items.playerr >= 180) 0414 items.playerr -= 180 0415 else 0416 items.playerr += 180 0417 } 0418 } else { 0419 /* Absolute mode */ 0420 var curpos = getPlayerRotation() 0421 items.playerr = items.playerr - (curpos === 270 ? -90 : curpos) 0422 if (!(maze[getId(items.playerx, items.playery)] & SOUTH)) { 0423 ++items.playery 0424 } else { 0425 items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/brick.wav") 0426 } 0427 } 0428 } 0429 0430 /* Check if success */ 0431 checkSuccess() 0432 } 0433 0434 function clickUp() { 0435 /* Move the player */ 0436 if ((!invisibleMode || !items.wallVisible) 0437 && (items.playery !== items.doory 0438 || items.playerx !== mazeColumns - 1)) { 0439 if (relativeMode) { 0440 /* Relative mode */ 0441 if (getPlayerRotation() === 270) { 0442 if (!(maze[getId(items.playerx, items.playery)] & EAST)) { 0443 ++items.playerx 0444 } else { 0445 items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/brick.wav") 0446 } 0447 } else if (getPlayerRotation() === 180) { 0448 if (!(maze[getId(items.playerx, items.playery)] & NORTH)) { 0449 --items.playery 0450 } else { 0451 items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/brick.wav") 0452 } 0453 } else if (getPlayerRotation() === 90) { 0454 if (!(maze[getId(items.playerx, items.playery)] & WEST)) { 0455 --items.playerx 0456 } else { 0457 items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/brick.wav") 0458 } 0459 } else { 0460 if (!(maze[getId(items.playerx, items.playery)] & SOUTH)) { 0461 ++items.playery 0462 } else { 0463 items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/brick.wav") 0464 } 0465 } 0466 } else { 0467 /* Absolute mode */ 0468 var curpos = getPlayerRotation() 0469 items.playerr = items.playerr - curpos + 180 0470 if (!(maze[getId(items.playerx, items.playery)] & NORTH)) { 0471 --items.playery 0472 } else { 0473 items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/brick.wav") 0474 } 0475 } 0476 } 0477 0478 /* Check if success */ 0479 checkSuccess() 0480 }