File indexing completed on 2024-04-21 14:43:37

0001 /* gcompris - memory.js
0002  *
0003  * SPDX-FileCopyrightText: 2014 JB BUTET
0004  *
0005  * Authors:
0006  *   Bruno Coudoin <bruno.coudoin@gcompris.net> (GTK+ version)
0007  *   JB BUTET <ashashiwa@gmail.com> (Qt Quick port)
0008  *   Timothée Giet <animtim@gmail.com>
0009  *
0010  *   SPDX-License-Identifier: GPL-3.0-or-later
0011  */
0012 .pragma library
0013 .import QtQuick 2.12 as Quick
0014 .import "qrc:/gcompris/src/core/core.js" as Core
0015 
0016 var url = "qrc:/gcompris/src/activities/memory/resource/"
0017 
0018 var items
0019 var numberOfLevel
0020 var nbOfPair
0021 var cardLeft
0022 var cardList
0023 
0024 function start(items_) {
0025 
0026     items = items_
0027 
0028     numberOfLevel = items.levels.length
0029     items.currentLevel = Core.getInitialLevel(numberOfLevel)
0030 
0031     initLevel()
0032 }
0033 
0034 function stop() {
0035 }
0036 
0037 function initLevel() {
0038     items.containerModel.clear()
0039     items.playQueue = []
0040     items.tuxTurn = false
0041     items.player2Turn = false
0042     items.selectionCount = 0
0043     items.blockClicks = false
0044 
0045     // compute the number of cards
0046     var columns = items.levels[items.currentLevel].columns
0047     var rows = items.levels[items.currentLevel].rows
0048     var images = items.levels[items.currentLevel].images
0049     var sounds = items.levels[items.currentLevel].sounds
0050     var texts = items.levels[items.currentLevel].texts
0051     var repeaterModels = items.levels[items.currentLevel].repeaterModels
0052     items.columns = columns
0053     items.rows = rows
0054     nbOfPair = rows * columns / 2
0055     cardLeft = nbOfPair * 2
0056 
0057     // Check the provided dataset has enough data
0058     var maxData = Math.max(
0059                 images ? images.length : 0,
0060                 sounds ? sounds.length : 0,
0061                 texts ? texts.length : 0,
0062                 repeaterModels ? repeaterModels.length : 0)
0063 
0064     if(rows * columns > maxData * 2) {
0065         console.log("ERROR: Memory dataset does not have enough data pairs at level ",
0066                     items.currentLevel + 1)
0067         return
0068     }
0069 
0070     // Create a list of indexes for the shuffling
0071     // This way we can keep the 3 lists in sync
0072     var shuffleIds = []
0073     for(var i = 0;  i < maxData; ++i) {
0074         shuffleIds.push(i)
0075     }
0076     Core.shuffle(shuffleIds)
0077 
0078     // place randomly a level-defined number of pairs
0079     cardList = []
0080     for(var ix = 0;  ix < nbOfPair; ++ix) {
0081         // select a random item
0082         for(var j = 0; j < 2; ++j) {
0083             cardList.push( {
0084                 image: images ? images[shuffleIds[ix]][j] : "",
0085                 sound: sounds ? sounds[shuffleIds[ix]][j] : "",
0086                 text: texts ? texts[shuffleIds[ix]][j] : "",
0087                 repeaterModel: repeaterModels ? repeaterModels[shuffleIds[ix]][j] : "",
0088                 matchCode: ix,
0089                 back: url + "backcard.svg",
0090                 emptyCard: url + "emptycard.svg"
0091             } )
0092         }
0093     }
0094 
0095     cardList = Core.shuffle(cardList)
0096 
0097     // fill the model
0098     for(i = 0;  i < cardList.length; ++i) {
0099         items.containerModel.append( { pairData_: cardList[i] } )
0100     }
0101 
0102     if(items.withTux || items.playerCount === 2) {
0103         items.player2Score.endTurn();
0104         items.player1Score.beginTurn();
0105     }
0106     else {
0107         items.player1Score.endTurn();
0108     }
0109 
0110     items.player1Score.playerScore = 0
0111     items.player2Score.playerScore = 0
0112 }
0113 
0114 // Return a pair of cards that have already been shown
0115 function getShownPair() {
0116     for(var i = 0;  i < nbOfPair * 2; ++i) {
0117         var cardItem1 = items.grid.getItemAtIndex(i)
0118         for(var j = 0;  j < nbOfPair * 2; ++j) {
0119             var cardItem2 = items.grid.getItemAtIndex(j)
0120             if(i != j &&
0121                 !cardItem1.isFound &&
0122                 cardItem1.isShown &&
0123                 !cardItem2.isFound &&
0124                 cardItem2.isShown &&
0125                 (cardItem1.pairData.matchCode ===
0126                  cardItem2.pairData.matchCode) ) {
0127                 return [cardItem1, cardItem2]
0128             }
0129         }
0130     }
0131     return
0132 }
0133 
0134 // Calc randomly if Tux is a good player
0135 // Return true if Tux should play correctly
0136 function getRandomTuxIsGood() {
0137     return Math.random() * numberOfLevel < items.currentLevel
0138 }
0139 
0140 function chooseCard() {
0141 
0142     // Tux looks in the shown card to make his choice
0143     if(getRandomTuxIsGood()) {
0144         var shownPair = getShownPair()
0145         if(shownPair) {
0146             if(shownPair[0].isBack) {
0147                 return shownPair[0]
0148             } else {
0149                 return shownPair[1]
0150             }
0151         }
0152     }
0153 
0154     // If no pairs shown select a random card
0155     var listCardNonReturned = []
0156     for(var i = 0;  i < cardList.length; ++i) {
0157         if (items.grid.getItemAtIndex(i).isFound == false &&
0158             items.grid.getItemAtIndex(i).isBack)
0159             listCardNonReturned.push(items.grid.getItemAtIndex(i))
0160     }
0161 
0162     //select randomly a card in it
0163     return listCardNonReturned[Math.floor(Math.random() * listCardNonReturned.length)]
0164 }
0165 
0166 function reverseCardsIfNeeded() {
0167     if(items.playQueue.length >= 2) {
0168         items.selectionCount = 0
0169         var item1 = items.playQueue.shift()
0170         var item2 = items.playQueue.shift()
0171         var tuxTurn = item1.tuxTurn
0172 
0173         if (item1.card.pairData.matchCode ===
0174             item2.card.pairData.matchCode) {
0175             // the 2 cards are the same
0176             item1.card.isBack = false // stay faced
0177             item1.card.isFound = true // signal for hidden state
0178             item2.card.isBack = false
0179             item2.card.isFound = true
0180             cardLeft = cardLeft - 2
0181 
0182             if (tuxTurn) {
0183                 items.player2Score.playerScore++
0184             }
0185             else if(items.playerCount === 2) {
0186                 if(items.player2Turn) {
0187                     items.player2Score.playerScore++
0188                 }
0189                 else {
0190                     items.player1Score.playerScore++
0191                 }
0192             }
0193             else {
0194                 items.player1Score.playerScore++
0195             }
0196 
0197             if(cardLeft === 0) { // no more cards in the level
0198                 if(items.withTux) {
0199                     if (items.player2Score.playerScore < items.player1Score.playerScore) {
0200                         youWon()
0201                     }
0202                     else {
0203                         youLoose()
0204                     }
0205                 }
0206                 else {
0207                     youWon()
0208                 }
0209             } else {
0210                 if(items.withTux && items.tuxTurn) {
0211                     tuxPlay()
0212                 } else {
0213                     items.audioEffects.play('qrc:/gcompris/src/core/resource/sounds/win.wav')
0214                 }
0215             }
0216 
0217 
0218         } else {
0219             // pictures clicked are not the same
0220             item1.card.isBack = true
0221             item2.card.isBack = true
0222 
0223             if(items.withTux) {
0224                 items.tuxTurn = !items.tuxTurn
0225                 // The user lost, it's Tux turn
0226                 if(items.tuxTurn) {
0227                     items.player2Score.beginTurn()
0228                     items.player1Score.endTurn()
0229                     tuxPlay()
0230                 }
0231                 else {
0232                     items.player1Score.beginTurn()
0233                     items.player2Score.endTurn()
0234                 }
0235             }
0236 
0237             if(items.playerCount === 2) {
0238                 items.player2Turn = !items.player2Turn
0239                 if(items.player2Turn) {
0240                     items.player2Score.beginTurn()
0241                     items.player1Score.endTurn()
0242                 }
0243                 else {
0244                     items.player1Score.beginTurn()
0245                     items.player2Score.endTurn()
0246                 }
0247             }
0248         }
0249     }
0250 }
0251 
0252 function tuxPlay() {
0253     // choose a card
0254     chooseCard().selected()
0255 }
0256 
0257 
0258 function youWon() {
0259     items.blockClicks = true
0260     items.bonus.good("flower")
0261 }
0262 
0263 function youLoose() {
0264     items.blockClicks = true
0265     items.bonus.bad("flower")
0266 }
0267 
0268 function repeatCurrentLevel() {
0269     if (items.withTux) {
0270         initLevel()
0271     }
0272 }
0273 
0274 function nextLevel() {
0275     items.currentLevel = Core.getNextLevel(items.currentLevel, numberOfLevel);
0276     initLevel();
0277 }
0278 
0279 function previousLevel() {
0280     items.currentLevel = Core.getPreviousLevel(items.currentLevel, numberOfLevel);
0281     initLevel();
0282 }
0283 
0284 function dumpPlayQueue() {
0285     for(var i in items.playQueue)
0286         console.log(items.playQueue[i].card, items.playQueue[i].tuxTurn)
0287 }
0288 
0289 // Return true is we have enough to make a pair
0290 function addPlayQueue(card) {
0291     items.playQueue.push({'card': card, 'tuxTurn': items.tuxTurn})
0292     return items.playQueue.length >= 2
0293 }