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 }