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 }