File indexing completed on 2024-05-19 03:43:55
0001 /* GCompris - nine_men_morris.js 0002 * 0003 * SPDX-FileCopyrightText: 2016 Pulkit Gupta <pulkitnsit@gmail.com> 0004 * 0005 * Authors: 0006 * Pulkit Gupta <pulkitnsit@gmail.com> 0007 * 0008 * SPDX-License-Identifier: GPL-3.0-or-later 0009 */ 0010 .pragma library 0011 .import QtQuick 2.12 as Quick 0012 .import "qrc:/gcompris/src/core/core.js" as Core 0013 0014 var numberOfLevel = 5 0015 var items 0016 var url = "qrc:/gcompris/src/activities/nine_men_morris/resource/" 0017 var currentPiece 0018 var twoPlayer 0019 var stopper //For stopping game when doing reset 0020 var currentRepeater 0021 var otherRepeater 0022 var numberOfFirstPieces 0023 var numberOfSecondPieces 0024 var numberOfPieces 0025 var numberOfDragPoints 0026 var depthMax 0027 var tutorialInstructions = [ 0028 { 0029 "instruction": qsTr("You and Tux start with 9 pieces each, and take turns to place your pieces on the empty spots of the board (by clicking on the spots)."), 0030 "instructionImage" : "qrc:/gcompris/src/activities/nine_men_morris/resource/tutorial1.svg" 0031 }, 0032 { 0033 "instruction": qsTr("If you form a mill (line of 3 pieces), then select one of Tux's pieces to remove it. Pieces of formed mill can not be removed unless no other pieces are left on the board."), 0034 "instructionImage": "qrc:/gcompris/src/activities/nine_men_morris/resource/tutorial2.svg" 0035 }, 0036 { 0037 "instruction": qsTr("After all the pieces are placed, you and Tux will take turns to move them. Click on one of your pieces, and then on an adjacent empty spot to move it there. Green color spots indicates where you can move."), 0038 "instructionImage": "qrc:/gcompris/src/activities/nine_men_morris/resource/tutorial3.svg" 0039 }, 0040 { 0041 "instruction": qsTr("If you are left with 3 pieces, they gain the ability to 'fly' and can be moved to any vacant spot on the board."), 0042 "instructionImage": "qrc:/gcompris/src/activities/nine_men_morris/resource/tutorial4.svg" 0043 }, 0044 { 0045 "instruction": qsTr("If you immobilize the computer or leave it with less than 3 pieces, then you win the game."), 0046 "instructionImage": "qrc:/gcompris/src/activities/nine_men_morris/resource/tutorial5.svg" 0047 } 0048 ] 0049 0050 function start(items_, twoPlayer_) { 0051 items = items_ 0052 items.currentLevel = Core.getInitialLevel(numberOfLevel) 0053 twoPlayer = twoPlayer_ 0054 numberOfLevel = 6 0055 numberOfPieces = 9 0056 numberOfDragPoints = 24 0057 items.playSecond = false 0058 0059 // Creating drag points 0060 items.dragPointsModel.append({ 0061 "posX": 0.05, 0062 "posY": 0.95, 0063 "myIndex": 0 0064 }) 0065 items.dragPointsModel.append({ 0066 "posX": 0.5, 0067 "posY": 0.95, 0068 "myIndex": 1 0069 }) 0070 items.dragPointsModel.append({ 0071 "posX": 0.95, 0072 "posY": 0.95, 0073 "myIndex": 2 0074 }) 0075 items.dragPointsModel.append({ 0076 "posX": 0.2, 0077 "posY": 0.8, 0078 "myIndex": 3 0079 }) 0080 items.dragPointsModel.append({ 0081 "posX": 0.5, 0082 "posY": 0.8, 0083 "myIndex": 4 0084 }) 0085 items.dragPointsModel.append({ 0086 "posX": 0.8, 0087 "posY": 0.8, 0088 "myIndex": 5 0089 }) 0090 items.dragPointsModel.append({ 0091 "posX": 0.35, 0092 "posY": 0.65, 0093 "myIndex": 6 0094 }) 0095 items.dragPointsModel.append({ 0096 "posX": 0.5, 0097 "posY": 0.65, 0098 "myIndex": 7 0099 }) 0100 items.dragPointsModel.append({ 0101 "posX": 0.65, 0102 "posY": 0.65, 0103 "myIndex": 8 0104 }) 0105 items.dragPointsModel.append({ 0106 "posX": 0.05, 0107 "posY": 0.5, 0108 "myIndex": 9 0109 }) 0110 items.dragPointsModel.append({ 0111 "posX": 0.2, 0112 "posY": 0.5, 0113 "myIndex": 10 0114 }) 0115 items.dragPointsModel.append({ 0116 "posX": 0.35, 0117 "posY": 0.5, 0118 "myIndex": 11 0119 }) 0120 items.dragPointsModel.append({ 0121 "posX": 0.65, 0122 "posY": 0.5, 0123 "myIndex": 12 0124 }) 0125 items.dragPointsModel.append({ 0126 "posX": 0.8, 0127 "posY": 0.5, 0128 "myIndex": 13 0129 }) 0130 items.dragPointsModel.append({ 0131 "posX": 0.95, 0132 "posY": 0.5, 0133 "myIndex": 14 0134 }) 0135 items.dragPointsModel.append({ 0136 "posX": 0.35, 0137 "posY": 0.35, 0138 "myIndex": 15 0139 }) 0140 items.dragPointsModel.append({ 0141 "posX": 0.5, 0142 "posY": 0.35, 0143 "myIndex": 16 0144 }) 0145 items.dragPointsModel.append({ 0146 "posX": 0.65, 0147 "posY": 0.35, 0148 "myIndex": 17 0149 }) 0150 items.dragPointsModel.append({ 0151 "posX": 0.2, 0152 "posY": 0.2, 0153 "myIndex": 18 0154 }) 0155 items.dragPointsModel.append({ 0156 "posX": 0.500, 0157 "posY": 0.2, 0158 "myIndex": 19 0159 }) 0160 items.dragPointsModel.append({ 0161 "posX": 0.8, 0162 "posY": 0.2, 0163 "myIndex": 20 0164 }) 0165 items.dragPointsModel.append({ 0166 "posX": 0.05, 0167 "posY": 0.05, 0168 "myIndex": 21 0169 }) 0170 items.dragPointsModel.append({ 0171 "posX": 0.5, 0172 "posY": 0.05, 0173 "myIndex": 22 0174 }) 0175 items.dragPointsModel.append({ 0176 "posX": 0.95, 0177 "posY": 0.05, 0178 "myIndex": 23 0179 }) 0180 // For assigning left and right point 0181 for (var i = 0 ; i < numberOfDragPoints ; i++) { 0182 if(i % 3) 0183 items.dragPoints.itemAt(i).leftPoint = items.dragPoints.itemAt(i - 1) 0184 else 0185 items.dragPoints.itemAt(i).leftPoint = null 0186 if((i + 1) % 3) 0187 items.dragPoints.itemAt(i).rightPoint = items.dragPoints.itemAt(i + 1) 0188 else 0189 items.dragPoints.itemAt(i).rightPoint = null 0190 } 0191 0192 // Start assigning upper and lower point 0193 items.dragPoints.itemAt(0).upperPoint = items.dragPoints.itemAt(9) 0194 items.dragPoints.itemAt(0).lowerPoint = null 0195 items.dragPoints.itemAt(1).upperPoint = items.dragPoints.itemAt(4) 0196 items.dragPoints.itemAt(1).lowerPoint = null 0197 items.dragPoints.itemAt(2).upperPoint = items.dragPoints.itemAt(14) 0198 items.dragPoints.itemAt(2).lowerPoint = null 0199 items.dragPoints.itemAt(3).upperPoint = items.dragPoints.itemAt(10) 0200 items.dragPoints.itemAt(3).lowerPoint = null 0201 items.dragPoints.itemAt(4).upperPoint = items.dragPoints.itemAt(7) 0202 items.dragPoints.itemAt(4).lowerPoint = items.dragPoints.itemAt(1) 0203 items.dragPoints.itemAt(5).upperPoint = items.dragPoints.itemAt(13) 0204 items.dragPoints.itemAt(5).lowerPoint = null 0205 items.dragPoints.itemAt(6).upperPoint = items.dragPoints.itemAt(11) 0206 items.dragPoints.itemAt(6).lowerPoint = null 0207 items.dragPoints.itemAt(7).upperPoint = null 0208 items.dragPoints.itemAt(7).lowerPoint = items.dragPoints.itemAt(4) 0209 items.dragPoints.itemAt(8).upperPoint = items.dragPoints.itemAt(12) 0210 items.dragPoints.itemAt(8).lowerPoint = null 0211 items.dragPoints.itemAt(9).upperPoint = items.dragPoints.itemAt(21) 0212 items.dragPoints.itemAt(9).lowerPoint = items.dragPoints.itemAt(0) 0213 items.dragPoints.itemAt(10).upperPoint = items.dragPoints.itemAt(18) 0214 items.dragPoints.itemAt(10).lowerPoint = items.dragPoints.itemAt(3) 0215 items.dragPoints.itemAt(11).upperPoint = items.dragPoints.itemAt(15) 0216 items.dragPoints.itemAt(11).lowerPoint = items.dragPoints.itemAt(6) 0217 items.dragPoints.itemAt(12).upperPoint = items.dragPoints.itemAt(17) 0218 items.dragPoints.itemAt(12).lowerPoint = items.dragPoints.itemAt(8) 0219 items.dragPoints.itemAt(13).upperPoint = items.dragPoints.itemAt(20) 0220 items.dragPoints.itemAt(13).lowerPoint = items.dragPoints.itemAt(5) 0221 items.dragPoints.itemAt(14).upperPoint = items.dragPoints.itemAt(23) 0222 items.dragPoints.itemAt(14).lowerPoint = items.dragPoints.itemAt(2) 0223 items.dragPoints.itemAt(15).upperPoint = null 0224 items.dragPoints.itemAt(15).lowerPoint = items.dragPoints.itemAt(11) 0225 items.dragPoints.itemAt(16).upperPoint = items.dragPoints.itemAt(19) 0226 items.dragPoints.itemAt(16).lowerPoint = null 0227 items.dragPoints.itemAt(17).upperPoint = null 0228 items.dragPoints.itemAt(17).lowerPoint = items.dragPoints.itemAt(12) 0229 items.dragPoints.itemAt(18).upperPoint = null 0230 items.dragPoints.itemAt(18).lowerPoint = items.dragPoints.itemAt(10) 0231 items.dragPoints.itemAt(19).upperPoint = items.dragPoints.itemAt(22) 0232 items.dragPoints.itemAt(19).lowerPoint = items.dragPoints.itemAt(16) 0233 items.dragPoints.itemAt(20).upperPoint = null 0234 items.dragPoints.itemAt(20).lowerPoint = items.dragPoints.itemAt(13) 0235 items.dragPoints.itemAt(21).upperPoint = null 0236 items.dragPoints.itemAt(21).lowerPoint = items.dragPoints.itemAt(9) 0237 items.dragPoints.itemAt(22).upperPoint = null 0238 items.dragPoints.itemAt(22).lowerPoint = items.dragPoints.itemAt(19) 0239 items.dragPoints.itemAt(23).upperPoint = null 0240 items.dragPoints.itemAt(23).lowerPoint = items.dragPoints.itemAt(14) 0241 // End assigning upper and lower piece 0242 0243 if(twoPlayer) { 0244 items.tutorialSection.visible = false 0245 initLevel() 0246 } 0247 } 0248 0249 function stop() { 0250 items.trigTuxMove.stop(); 0251 } 0252 0253 function initLevel() { 0254 items.turn = 0 0255 items.gameDone = false 0256 items.firstPhase = true 0257 items.pieceBeingMoved = false 0258 numberOfFirstPieces = 0 0259 numberOfSecondPieces = 0 0260 items.firstPieceNumberCount = numberOfPieces 0261 items.secondPieceNumberCount = numberOfPieces 0262 items.instructionTxt = qsTr("Place a piece") 0263 depthMax = 2 0264 0265 // Clear first and second player pieces, and initialize dragPoints 0266 items.firstPlayerPieces.model.clear() 0267 items.secondPlayerPieces.model.clear() 0268 for (var i = 0 ; i < numberOfDragPoints ; ++i) 0269 items.dragPoints.itemAt(i).state = "AVAILABLE" 0270 0271 // Create first and second player pieces 0272 for (var i = 0 ; i < numberOfPieces ; ++i) { 0273 items.firstPlayerPiecesModel.append({}) 0274 items.secondPlayerPiecesModel.append({}) 0275 } 0276 0277 currentRepeater = items.firstPlayerPieces 0278 otherRepeater = items.secondPlayerPieces 0279 0280 stopper = false 0281 0282 if(items.playSecond) { 0283 initiatePlayer2() 0284 if(!twoPlayer) { 0285 var rand = Math.floor((Math.random() * numberOfDragPoints)) 0286 handleCreate(rand) 0287 } 0288 } 0289 else 0290 initiatePlayer1() 0291 } 0292 0293 function nextLevel() { 0294 items.currentLevel = Core.getNextLevel(items.currentLevel, numberOfLevel); 0295 reset(); 0296 } 0297 0298 function previousLevel() { 0299 items.currentLevel = Core.getPreviousLevel(items.currentLevel, numberOfLevel); 0300 reset(); 0301 } 0302 0303 function reset() { 0304 items.trigTuxMove.stop(); 0305 stopper = true; 0306 shouldComputerPlay(); 0307 items.player2score.endTurn(); 0308 items.player1score.beginTurn(); 0309 items.playSecond = !items.playSecond 0310 initLevel() 0311 } 0312 0313 //Initial values at the start of game when its player 1 turn 0314 function initiatePlayer1() { 0315 items.player2score.endTurn(); 0316 items.player1score.beginTurn(); 0317 0318 items.firstInitial.anchors.right = undefined 0319 items.firstInitial.anchors.top = items.player1score.bottom 0320 items.firstInitial.anchors.left = items.player1score.left 0321 0322 items.secondInitial.anchors.left = undefined 0323 items.secondInitial.anchors.right = items.player2score.right 0324 items.secondInitial.anchors.top = items.player2score.bottom 0325 } 0326 0327 //Initial values at the start of game when its player 1 turn 0328 function initiatePlayer2() { 0329 0330 items.player1score.endTurn(); 0331 items.player2score.beginTurn(); 0332 0333 items.secondInitial.anchors.right = undefined 0334 items.secondInitial.anchors.top = items.player1score.bottom 0335 items.secondInitial.anchors.left = items.player1score.left 0336 0337 items.firstInitial.anchors.left = undefined 0338 items.firstInitial.anchors.right = items.player2score.right 0339 items.firstInitial.anchors.top = items.player2score.bottom 0340 } 0341 0342 //Change scale of score boxes according to turns 0343 function changeScale() { 0344 if(items.playSecond) { 0345 if(items.turn % 2 == 0) { 0346 items.player2score.beginTurn(); 0347 items.player1score.endTurn(); 0348 } 0349 else { 0350 items.player1score.beginTurn(); 0351 items.player2score.endTurn(); 0352 } 0353 } 0354 else { 0355 if(items.turn % 2 == 0) { 0356 items.player1score.beginTurn(); 0357 items.player2score.endTurn(); 0358 } 0359 else { 0360 items.player2score.beginTurn(); 0361 items.player1score.endTurn(); 0362 } 0363 } 0364 } 0365 0366 //Create the piece at given position 0367 function handleCreate(index) { 0368 items.pieceBeingMoved = true 0369 currentPiece = currentRepeater.itemAt(items.turn / 2) 0370 if(currentPiece.state == "2") { 0371 items.secondPieceNumberCount-- 0372 numberOfSecondPieces++ 0373 } 0374 else { 0375 items.firstPieceNumberCount-- 0376 numberOfFirstPieces++ 0377 } 0378 currentPiece.move(items.dragPoints.itemAt(index)) 0379 } 0380 0381 function secondPhase() { 0382 items.firstPhase = false 0383 for (var i = 0 ; i < numberOfDragPoints ; ++i) { 0384 if(items.dragPoints.itemAt(i).state != "1" && items.dragPoints.itemAt(i).state != "2") 0385 items.dragPoints.itemAt(i).state = "EMPTY" 0386 } 0387 0388 items.instructionTxt = qsTr("Move a piece") 0389 } 0390 0391 function pieceSelected(pieceIndex) { 0392 currentPiece.isSelected = false 0393 currentPiece = currentRepeater.itemAt(pieceIndex) 0394 currentPiece.isSelected = true 0395 0396 if((currentPiece.state == "1" && numberOfFirstPieces > 3) || 0397 (currentPiece.state == "2" && numberOfSecondPieces > 3)) { 0398 0399 for (var i = 0 ; i < numberOfDragPoints ; ++i) { 0400 if(items.dragPoints.itemAt(i).state == "EMPTY" || items.dragPoints.itemAt(i).state == "AVAILABLE") 0401 items.dragPoints.itemAt(i).state = "UNAVAILABLE" 0402 } 0403 0404 // Now assign values 0405 var index = currentRepeater.itemAt(pieceIndex).parentIndex // Drag Point index 0406 var dragPoint = items.dragPoints.itemAt(index) 0407 0408 if(dragPoint.leftPoint) { 0409 if(dragPoint.leftPoint.state == "UNAVAILABLE") 0410 dragPoint.leftPoint.state = "AVAILABLE" 0411 } 0412 if(dragPoint.upperPoint) { 0413 if(dragPoint.upperPoint.state == "UNAVAILABLE") 0414 dragPoint.upperPoint.state = "AVAILABLE" 0415 } 0416 if(dragPoint.rightPoint) { 0417 if(dragPoint.rightPoint.state == "UNAVAILABLE") 0418 dragPoint.rightPoint.state = "AVAILABLE" 0419 } 0420 if(dragPoint.lowerPoint) { 0421 if(dragPoint.lowerPoint.state == "UNAVAILABLE") 0422 dragPoint.lowerPoint.state = "AVAILABLE" 0423 } 0424 } 0425 else { 0426 for (var i = 0 ; i < numberOfDragPoints ; ++i) { 0427 if(items.dragPoints.itemAt(i).state == "EMPTY" || items.dragPoints.itemAt(i).state == "UNAVAILABLE") 0428 items.dragPoints.itemAt(i).state = "AVAILABLE" 0429 } 0430 } 0431 } 0432 0433 function movePiece(index) { 0434 items.pieceBeingMoved = true 0435 currentPiece.pieceParent.state = "EMPTY" 0436 currentPiece.isSelected = false 0437 for (var i = 0 ; i < numberOfDragPoints ; ++i) { 0438 if(items.dragPoints.itemAt(i).state != "1" && items.dragPoints.itemAt(i).state != "2") 0439 items.dragPoints.itemAt(i).state = "EMPTY" 0440 } 0441 currentPiece.move(items.dragPoints.itemAt(index)) 0442 } 0443 0444 function shouldComputerPlay() { 0445 if(!twoPlayer) { 0446 if(items.turn % 2 && items.playSecond == false && stopper == false) { 0447 items.trigTuxMove.start() 0448 } 0449 else if((items.turn % 2 == 0) && items.playSecond && stopper == false) { 0450 items.trigTuxMove.start() 0451 } 0452 else 0453 items.pieceBeingMoved = false 0454 } 0455 else 0456 items.pieceBeingMoved = false 0457 } 0458 0459 function doMove() { 0460 if(items.firstPhase) { 0461 if(items.currentLevel < 4) 0462 var index = setFirstPhaseMove() 0463 else { 0464 var boardPiecesLeft = items.firstPieceNumberCount + items.secondPieceNumberCount 0465 var board = getBoard() 0466 var index = alphabeta(depthMax, -9000, 9000, 2, board, boardPiecesLeft, false) 0467 } 0468 handleCreate(index) 0469 } 0470 else if(items.currentLevel < 4 && ((currentPiece.state == "2" && numberOfFirstPieces > 3) || 0471 (currentPiece.state == "1" && numberOfSecondPieces > 3))) { 0472 var index = setSecondPhaseMove() 0473 currentPiece = currentRepeater.itemAt(index[0]) 0474 movePiece(index[1]) 0475 } 0476 else if(items.currentLevel < 4) { 0477 var index = setThirdPhaseMove() 0478 currentPiece = currentRepeater.itemAt(index[0]) 0479 movePiece(index[1]) 0480 } 0481 else { 0482 var noOfPlayerPieces = items.playSecond ? numberOfSecondPieces : numberOfFirstPieces 0483 var noOfComputerPieces = items.playSecond ? numberOfFirstPieces : numberOfSecondPieces 0484 var board = getBoard() 0485 var index = alphabeta(depthMax, -9000, 9000, 2, board, 0, false) 0486 currentPiece = currentRepeater.itemAt(items.dragPoints.itemAt(index[0]).pieceIndex) 0487 movePiece(index[1]) 0488 } 0489 } 0490 0491 function setFirstPhaseMove() { 0492 //Assigning States -> State "1" or "2" is used for identifying player and computer 0493 var playerState = items.playSecond ? "2" : "1" 0494 var computerState = items.playSecond ? "1" : "2" 0495 0496 if(items.currentLevel > 0) { 0497 var value = evaluateBoard(computerState) 0498 if(value != -1) 0499 return value 0500 } 0501 0502 if(items.currentLevel > 1) { 0503 var value = evaluateBoard(playerState) 0504 if(value != -1) 0505 return value 0506 } 0507 0508 var found = false 0509 while (!found) { 0510 var randno = Math.floor((Math.random() * numberOfDragPoints)) 0511 if(items.dragPoints.itemAt(randno).state == "EMPTY" || items.dragPoints.itemAt(randno).state == "AVAILABLE") 0512 found = true 0513 } 0514 return randno 0515 } 0516 0517 function evaluateBoard(state) { 0518 for(var i = 0 ; i < numberOfDragPoints ; ++i) { 0519 if(items.dragPoints.itemAt(i).state == "EMPTY" || items.dragPoints.itemAt(i).state == "AVAILABLE") { 0520 if(checkMill(i,state)) 0521 return i 0522 } 0523 } 0524 return -1 0525 } 0526 0527 function setSecondPhaseMove() { 0528 var index = [] 0529 var found = false 0530 0531 if(items.currentLevel > 0) { 0532 for(var i = 0 ; i < numberOfPieces ; ++i) { 0533 var piece = currentRepeater.itemAt(i) 0534 if(piece.visible) { 0535 index[0] = i 0536 if(piece.pieceParent.leftPoint && piece.pieceParent.leftPoint.state == "EMPTY") { 0537 if(checkMill(piece.pieceParent.leftPoint.index, piece.state, "left")) { 0538 index[1] = piece.pieceParent.leftPoint.index 0539 found = true 0540 break 0541 } 0542 } 0543 if(piece.pieceParent.rightPoint && piece.pieceParent.rightPoint.state == "EMPTY") { 0544 if(checkMill(piece.pieceParent.rightPoint.index, piece.state, "right")) { 0545 index[1] = piece.pieceParent.rightPoint.index 0546 found = true 0547 break 0548 } 0549 } 0550 if(piece.pieceParent.upperPoint && piece.pieceParent.upperPoint.state == "EMPTY") { 0551 if(checkMill(piece.pieceParent.upperPoint.index, piece.state, "upper")) { 0552 index[1] = piece.pieceParent.upperPoint.index 0553 found = true 0554 break 0555 } 0556 } 0557 if(piece.pieceParent.lowerPoint && piece.pieceParent.lowerPoint.state == "EMPTY") { 0558 if(checkMill(piece.pieceParent.lowerPoint.index, piece.state, "lower")) { 0559 index[1] = piece.pieceParent.lowerPoint.index 0560 found = true 0561 break 0562 } 0563 } 0564 } 0565 } 0566 if(found) 0567 return index 0568 } 0569 0570 var playerState = items.playSecond ? "2" : "1" 0571 if(items.currentLevel > 1) { 0572 for(var i = 0 ; i < numberOfPieces ; ++i) { 0573 var piece = currentRepeater.itemAt(i) 0574 if(piece.visible) { 0575 index[0] = i 0576 if(piece.pieceParent.leftPoint && piece.pieceParent.leftPoint.state == "EMPTY") { 0577 if(checkMillPossible(piece.pieceParent.leftPoint.index, playerState)) { 0578 index[1] = piece.pieceParent.leftPoint.index 0579 found = true 0580 break 0581 } 0582 } 0583 if(piece.pieceParent.rightPoint && piece.pieceParent.rightPoint.state == "EMPTY") { 0584 if(checkMillPossible(piece.pieceParent.rightPoint.index, playerState)) { 0585 index[1] = piece.pieceParent.rightPoint.index 0586 found = true 0587 break 0588 } 0589 } 0590 if(piece.pieceParent.upperPoint && piece.pieceParent.upperPoint.state == "EMPTY") { 0591 if(checkMillPossible(piece.pieceParent.upperPoint.index, playerState)) { 0592 index[1] = piece.pieceParent.upperPoint.index 0593 found = true 0594 break 0595 } 0596 } 0597 if(piece.pieceParent.lowerPoint && piece.pieceParent.lowerPoint.state == "EMPTY") { 0598 if(checkMillPossible(piece.pieceParent.lowerPoint.index, playerState)) { 0599 index[1] = piece.pieceParent.lowerPoint.index 0600 found = true 0601 break 0602 } 0603 } 0604 } 0605 } 0606 if(found) 0607 return index 0608 } 0609 0610 var permittedPieceIndex = [] 0611 for(var i = 0 ; i < numberOfPieces ; ++i) { 0612 if(currentRepeater.itemAt(i).visible) { 0613 if(checkMovablePieces(currentRepeater.itemAt(i).pieceParent.index)) 0614 permittedPieceIndex.push(i) 0615 } 0616 } 0617 0618 if(!permittedPieceIndex.length) { 0619 for(var i = 0 ; i < numberOfPieces ; ++i) { 0620 if(currentRepeater.itemAt(i).visible) 0621 permittedPieceIndex.push(i) 0622 } 0623 } 0624 0625 var found = false 0626 while (!found) { 0627 var randno = Math.floor((Math.random() * permittedPieceIndex.length)) 0628 index[0] = permittedPieceIndex[randno] 0629 var permittedPointIndex = [] 0630 var dragPoint = currentRepeater.itemAt(index[0]).pieceParent 0631 0632 if(dragPoint.leftPoint && dragPoint.leftPoint.state == "EMPTY") { 0633 permittedPointIndex.push(dragPoint.leftPoint.index) 0634 } 0635 if(dragPoint.rightPoint && dragPoint.rightPoint.state == "EMPTY") { 0636 permittedPointIndex.push(dragPoint.rightPoint.index) 0637 } 0638 if(dragPoint.upperPoint && dragPoint.upperPoint.state == "EMPTY") { 0639 permittedPointIndex.push(dragPoint.upperPoint.index) 0640 } 0641 if(dragPoint.lowerPoint && dragPoint.lowerPoint.state == "EMPTY") { 0642 permittedPointIndex.push(dragPoint.lowerPoint.index) 0643 } 0644 if(permittedPointIndex.length) { 0645 var randNo = Math.floor((Math.random() * permittedPointIndex.length)) 0646 index[1] = permittedPointIndex[randNo] 0647 found = true 0648 } 0649 } 0650 return index 0651 } 0652 0653 function checkMillPossible(index, state) { 0654 0655 // thirdPhase is true if opponent can move its piece anywhere 0656 var thirdPhase = (items.playSecond && numberOfSecondPieces < 4) || (!items.playSecond && numberOfFirstPieces < 4) 0657 var dragPoint = items.dragPoints.itemAt(index) 0658 0659 if(dragPoint.leftPoint && dragPoint.leftPoint.leftPoint) { 0660 if(state == dragPoint.leftPoint.state && state == dragPoint.leftPoint.leftPoint.state) { 0661 if((dragPoint.upperPoint && state == dragPoint.upperPoint.state) || 0662 (dragPoint.lowerPoint && state == dragPoint.lowerPoint.state) || thirdPhase) 0663 return true; 0664 } 0665 } 0666 if(dragPoint.upperPoint && dragPoint.upperPoint.upperPoint) { 0667 if(state == dragPoint.upperPoint.state && state == dragPoint.upperPoint.upperPoint.state) { 0668 if((dragPoint.leftPoint && state == dragPoint.leftPoint.state) || 0669 (dragPoint.rightPoint && state == dragPoint.rightPoint.state) || thirdPhase) 0670 return true; 0671 } 0672 } 0673 if(dragPoint.rightPoint && dragPoint.rightPoint.rightPoint) { 0674 if(state == dragPoint.rightPoint.state && state == dragPoint.rightPoint.rightPoint.state) { 0675 if((dragPoint.upperPoint && state == dragPoint.upperPoint.state) || 0676 (dragPoint.lowerPoint && state == dragPoint.lowerPoint.state) || thirdPhase) 0677 return true; 0678 } 0679 } 0680 if(dragPoint.lowerPoint && dragPoint.lowerPoint.lowerPoint) { 0681 if(state == dragPoint.lowerPoint.state && state == dragPoint.lowerPoint.lowerPoint.state) { 0682 if((dragPoint.leftPoint && state == dragPoint.leftPoint.state) || 0683 (dragPoint.rightPoint && state == dragPoint.rightPoint.state) || thirdPhase) 0684 return true; 0685 } 0686 } 0687 if(dragPoint.lowerPoint && dragPoint.upperPoint) { 0688 if(state == dragPoint.lowerPoint.state && state == dragPoint.upperPoint.state) { 0689 if((dragPoint.leftPoint && state == dragPoint.leftPoint.state) || 0690 (dragPoint.rightPoint && state == dragPoint.rightPoint.state) || thirdPhase) 0691 return true; 0692 } 0693 } 0694 if(dragPoint.leftPoint && dragPoint.rightPoint) { 0695 if(state == dragPoint.leftPoint.state && state == dragPoint.rightPoint.state) { 0696 if((dragPoint.upperPoint && state == dragPoint.upperPoint.state) || 0697 (dragPoint.lowerPoint && state == dragPoint.lowerPoint.state) || thirdPhase) 0698 return true; 0699 } 0700 } 0701 return false; 0702 } 0703 0704 function setThirdPhaseMove() { 0705 0706 //Assigning States -> State "1" or "2" is used for identifying player and computer 0707 var playerState = items.playSecond ? "2" : "1" 0708 var computerState = items.playSecond ? "1" : "2" 0709 var index = [] 0710 0711 if(items.currentLevel > 1) { 0712 for(var i = 0 ; i < numberOfDragPoints ; ++i) { 0713 if(items.dragPoints.itemAt(i).state == "EMPTY") { 0714 var value = checkMillThirdPhase(i, computerState) 0715 if(value != -1) { 0716 index[0] = value 0717 index[1] = i 0718 return index 0719 } 0720 } 0721 } 0722 } 0723 0724 var permittedPieceIndex = [] 0725 for(var i = 0 ; i < numberOfPieces ; ++i) { 0726 if(currentRepeater.itemAt(i).visible) { 0727 if(!checkMillPossible(currentRepeater.itemAt(i).pieceParent.index, playerState)) { 0728 permittedPieceIndex.push(i) 0729 } 0730 } 0731 } 0732 0733 if(!permittedPieceIndex.length) { 0734 for(var i = 0 ; i < numberOfPieces ; ++i) { 0735 if(currentRepeater.itemAt(i).visible) 0736 permittedPieceIndex.push(i) 0737 } 0738 } 0739 0740 var randno = Math.floor((Math.random() * permittedPieceIndex.length)) 0741 index[0] = permittedPieceIndex[randno] 0742 0743 if(items.currentLevel > 2) { 0744 for(var i = 0 ; i < numberOfDragPoints ; ++i) { 0745 if(items.dragPoints.itemAt(i).state == "EMPTY") { 0746 if(checkMillPossible(i,playerState)) { 0747 index[1] = i 0748 return index 0749 } 0750 } 0751 } 0752 } 0753 0754 for(var i = 0 ; i < numberOfDragPoints ; ++i) { 0755 var dragPoint = items.dragPoints.itemAt(i) 0756 0757 if(dragPoint.state == "EMPTY" && 0758 ((dragPoint.leftPoint && dragPoint.leftPoint.state == computerState 0759 && dragPoint.leftPoint.pieceIndex != index[0]) || 0760 (dragPoint.rightPoint && dragPoint.rightPoint.state == computerState 0761 && dragPoint.rightPoint.pieceIndex != index[0]) || 0762 (dragPoint.upperPoint && dragPoint.upperPoint.state == computerState 0763 && dragPoint.upperPoint.pieceIndex != index[0]) || 0764 (dragPoint.lowerPoint && dragPoint.lowerPoint.state == computerState 0765 && dragPoint.lowerPoint.pieceIndex != index[0]))) { 0766 index[1] = i 0767 return index 0768 } 0769 } 0770 0771 var permittedPointIndex = [] 0772 for(var i = 0 ; i < numberOfDragPoints ; ++i) { 0773 if(items.dragPoints.itemAt(i).state == "EMPTY") 0774 permittedPointIndex.push(i) 0775 } 0776 randno = Math.floor((Math.random() * permittedPointIndex.length)) 0777 index[1] = permittedPointIndex[randno] 0778 return index 0779 } 0780 0781 function checkMillThirdPhase(index, state) { 0782 0783 var dragPoint = items.dragPoints.itemAt(index) 0784 if(dragPoint.leftPoint && dragPoint.leftPoint.leftPoint) { 0785 if(state == dragPoint.leftPoint.state && state == dragPoint.leftPoint.leftPoint.state) { 0786 for(var i = 0 ; i < numberOfPieces ; ++i) { 0787 if(currentRepeater.itemAt(i).visible && i != dragPoint.leftPoint.pieceIndex 0788 && i != dragPoint.leftPoint.leftPoint.pieceIndex) { 0789 return i 0790 } 0791 } 0792 } 0793 } 0794 0795 if(dragPoint.upperPoint && dragPoint.upperPoint.upperPoint) { 0796 if(state == dragPoint.upperPoint.state && state == dragPoint.upperPoint.upperPoint.state) { 0797 for(var i = 0 ; i < numberOfPieces ; ++i) { 0798 if(currentRepeater.itemAt(i).visible && i != dragPoint.upperPoint.pieceIndex 0799 && i != dragPoint.upperPoint.upperPoint.pieceIndex) { 0800 return i 0801 } 0802 } 0803 } 0804 } 0805 if(dragPoint.rightPoint && dragPoint.rightPoint.rightPoint) { 0806 if(state == dragPoint.rightPoint.state && state == dragPoint.rightPoint.rightPoint.state) { 0807 for(var i = 0 ; i < numberOfPieces ; ++i) { 0808 if(currentRepeater.itemAt(i).visible && i != dragPoint.rightPoint.pieceIndex 0809 && i != dragPoint.rightPoint.rightPoint.pieceIndex) { 0810 return i 0811 } 0812 } 0813 } 0814 } 0815 if(dragPoint.lowerPoint && dragPoint.lowerPoint.lowerPoint) { 0816 if(state == dragPoint.lowerPoint.state && state == dragPoint.lowerPoint.lowerPoint.state) { 0817 for(var i = 0 ; i < numberOfPieces ; ++i) { 0818 if(currentRepeater.itemAt(i).visible && i != dragPoint.lowerPoint.pieceIndex 0819 && i != dragPoint.lowerPoint.lowerPoint.pieceIndex) { 0820 return i 0821 } 0822 } 0823 } 0824 } 0825 if(dragPoint.lowerPoint && dragPoint.upperPoint) { 0826 if(state == dragPoint.lowerPoint.state && state == dragPoint.upperPoint.state) { 0827 for(var i = 0 ; i < numberOfPieces ; ++i) { 0828 if(currentRepeater.itemAt(i).visible && i != dragPoint.lowerPoint.pieceIndex 0829 && i != dragPoint.upperPoint.pieceIndex) { 0830 return i 0831 } 0832 } 0833 } 0834 } 0835 if(dragPoint.leftPoint && dragPoint.rightPoint) { 0836 if(state == dragPoint.leftPoint.state && state == dragPoint.rightPoint.state) { 0837 for(var i = 0 ; i < numberOfPieces ; ++i) { 0838 if(currentRepeater.itemAt(i).visible && i != dragPoint.leftPoint.pieceIndex 0839 && i != dragPoint.rightPoint.pieceIndex) { 0840 return i 0841 } 0842 } 0843 } 0844 } 0845 return -1 0846 } 0847 0848 // continueGame() called by Piece when its animation stops and checkMill(piece) is false or 0849 // called after removePiece(index) has removed a piece 0850 function continueGame() { 0851 items.turn ++ 0852 if(items.turn == (2 * numberOfPieces) && items.firstPhase) { 0853 secondPhase() 0854 items.turn -- 0855 checkGameWon() 0856 return 0857 } 0858 if(items.turn % 2) { 0859 currentRepeater = items.secondPlayerPieces 0860 otherRepeater = items.firstPlayerPieces 0861 } 0862 else { 0863 currentRepeater = items.firstPlayerPieces 0864 otherRepeater = items.secondPlayerPieces 0865 } 0866 changeScale() 0867 shouldComputerPlay(); 0868 } 0869 0870 // position value is only used when checkMill is called by setSecondPhaseMove or getSecondPhaseRemoveIndex function 0871 // Else it is declared as undefined by default 0872 function checkMill(index, state, position) { 0873 0874 var dragPoint = items.dragPoints.itemAt(index) 0875 if(dragPoint.leftPoint && dragPoint.leftPoint.leftPoint && position != "left" && position != "right") { 0876 if(state == dragPoint.leftPoint.state && state == dragPoint.leftPoint.leftPoint.state) 0877 return true; 0878 } 0879 if(dragPoint.upperPoint && dragPoint.upperPoint.upperPoint && position != "upper" && position != "lower") { 0880 if(state == dragPoint.upperPoint.state && state == dragPoint.upperPoint.upperPoint.state) 0881 return true; 0882 } 0883 if(dragPoint.rightPoint && dragPoint.rightPoint.rightPoint && position != "right" && position != "left") { 0884 if(state == dragPoint.rightPoint.state && state == dragPoint.rightPoint.rightPoint.state) 0885 return true; 0886 } 0887 if(dragPoint.lowerPoint && dragPoint.lowerPoint.lowerPoint && position != "lower" && position != "upper") { 0888 if(state == dragPoint.lowerPoint.state && state == dragPoint.lowerPoint.lowerPoint.state) 0889 return true; 0890 } 0891 if(dragPoint.lowerPoint && dragPoint.upperPoint && position != "lower" && position != "upper") { 0892 if(state == dragPoint.lowerPoint.state && state == dragPoint.upperPoint.state) 0893 return true; 0894 } 0895 if(dragPoint.leftPoint && dragPoint.rightPoint && position != "left" && position != "right") { 0896 if(state == dragPoint.leftPoint.state && state == dragPoint.rightPoint.state) 0897 return true; 0898 } 0899 return false; 0900 } 0901 0902 //check movable pieces 0903 function checkMovablePieces(index) { 0904 var dragPoint = items.dragPoints.itemAt(index) 0905 if(dragPoint.leftPoint && dragPoint.leftPoint.state == "EMPTY") { 0906 return true; 0907 } 0908 if(dragPoint.rightPoint && dragPoint.rightPoint.state == "EMPTY") { 0909 return true; 0910 } 0911 if(dragPoint.upperPoint && dragPoint.upperPoint.state == "EMPTY") { 0912 return true; 0913 } 0914 if(dragPoint.lowerPoint && dragPoint.lowerPoint.state == "EMPTY") { 0915 return true; 0916 } 0917 return false; 0918 } 0919 0920 // updateRemovablePiece called by Piece when its animation stops and checkMill(piece) is true 0921 function updateRemovablePiece() { 0922 0923 if(twoPlayer || ((items.turn % 2) && items.playSecond) || (!(items.turn % 2) && !items.playSecond)) { 0924 var foundOne = false 0925 for(var i = 0 ; i < numberOfPieces ; ++i) { 0926 var piece = otherRepeater.itemAt(i) 0927 if(piece.parentIndex != -1) { 0928 if(!checkMill(piece.parentIndex, piece.state) && piece.visible) { 0929 foundOne = true 0930 piece.canBeRemoved = true // Mark pieces of other player for removal 0931 } 0932 } 0933 } 0934 if(!foundOne) { 0935 for(var i = 0 ; i < numberOfPieces ; ++i) { 0936 if(otherRepeater.itemAt(i).parentIndex != -1 && otherRepeater.itemAt(i).visible) 0937 otherRepeater.itemAt(i).canBeRemoved = true 0938 } 0939 } 0940 items.instructionTxt = qsTr("Remove a piece") 0941 } 0942 else if(items.currentLevel < 4) { 0943 if(items.firstPhase) 0944 otherRepeater.itemAt(getFirstPhaseRemoveIndex()).remove() 0945 else 0946 otherRepeater.itemAt(getSecondPhaseRemoveIndex()).remove() 0947 } 0948 else { 0949 var board = getBoard() 0950 var boardPiecesLeft = items.firstPieceNumberCount + items.secondPieceNumberCount 0951 var index = alphabeta(depthMax, -9000, 9000, 2, board, boardPiecesLeft, true) 0952 var pieceIndex = items.dragPoints.itemAt(index).pieceIndex 0953 otherRepeater.itemAt(pieceIndex).remove() 0954 } 0955 } 0956 0957 function getFirstPhaseRemoveIndex() { 0958 0959 var playerState = items.playSecond ? "2" : "1" 0960 var permittedIndex = []; 0961 for(var i = 0 ; i < numberOfPieces ; ++i) { 0962 var piece = otherRepeater.itemAt(i) 0963 if(piece.parentIndex != -1) { 0964 if(!checkMill(piece.parentIndex, piece.state) && piece.visible) 0965 permittedIndex.push(i) 0966 } 0967 } 0968 if(permittedIndex.length == 0) { 0969 for(var i = 0 ; i < numberOfPieces ; ++i) { 0970 if((otherRepeater.itemAt(i).parentIndex != -1) && (otherRepeater.itemAt(i).visible)) 0971 permittedIndex.push(i) 0972 } 0973 } 0974 0975 if(items.currentLevel > 3) { 0976 var index = evaluateBoard(playerState) 0977 if(index != -1) { 0978 var value = -1 0979 var dragPoint = items.dragPoints.itemAt(index) 0980 if(dragPoint.leftPoint) 0981 value = checkRemovedIndex(playerState, dragPoint.leftPoint, 0982 dragPoint.leftPoint.leftPoint, permittedIndex) 0983 if(value != -1) 0984 return value 0985 0986 if(dragPoint.upperPoint) 0987 value = checkRemovedIndex(playerState, dragPoint.upperPoint, 0988 dragPoint.upperPoint.upperPoint, permittedIndex) 0989 if(value != -1) 0990 return value 0991 0992 if(dragPoint.rightPoint) 0993 value = checkRemovedIndex(playerState, dragPoint.rightPoint, 0994 dragPoint.rightPoint.rightPoint, permittedIndex) 0995 if(value != -1) 0996 return value 0997 0998 if(dragPoint.lowerPoint) 0999 value = checkRemovedIndex(playerState, dragPoint.lowerPoint, 1000 dragPoint.lowerPoint.lowerPoint, permittedIndex) 1001 if(value != -1) 1002 return value 1003 1004 if(dragPoint.lowerPoint) 1005 value = checkRemovedIndex(playerState, dragPoint.lowerPoint, 1006 dragPoint.upperPoint, permittedIndex) 1007 if(value != -1) 1008 return value 1009 1010 if(dragPoint.leftPoint) 1011 value = checkRemovedIndex(playerState, dragPoint.leftPoint, 1012 dragPoint.rightPoint, permittedIndex) 1013 if(value != -1) 1014 return value 1015 } 1016 } 1017 1018 var randno = Math.floor((Math.random() * permittedIndex.length)) 1019 return permittedIndex[randno] 1020 } 1021 1022 function checkRemovedIndex(state,first,second,permittedIndex) { 1023 1024 if(second) { 1025 if(state == first.state && state == second.state) { 1026 if(Math.floor((Math.random() * 2))) { 1027 for (var i = 0 ; i < permittedIndex.length ; ++ i) { 1028 if(permittedIndex[i] == first.pieceIndex) 1029 return first.pieceIndex 1030 } 1031 for (var i = 0 ; i < permittedIndex.length ; ++ i) { 1032 if(permittedIndex[i] == second.pieceIndex) 1033 return second.pieceIndex 1034 } 1035 } 1036 else { 1037 for (var i = 0 ; i < permittedIndex.length ; ++ i) { 1038 if(permittedIndex[i] == second.pieceIndex) 1039 return second.pieceIndex 1040 } 1041 for (var i = 0 ; i < permittedIndex.length ; ++ i) { 1042 if(permittedIndex[i] == first.pieceIndex) 1043 return first.pieceIndex 1044 } 1045 } 1046 } 1047 } 1048 return -1 1049 } 1050 1051 function getSecondPhaseRemoveIndex() { 1052 var permittedIndex = []; 1053 for(var i = 0 ; i < numberOfPieces ; ++i) { 1054 var piece = otherRepeater.itemAt(i) 1055 if(piece.parentIndex != -1) { 1056 if(piece.visible && !checkMill(piece.parentIndex, piece.state)) 1057 permittedIndex.push(i) 1058 } 1059 } 1060 1061 if(permittedIndex.length == 0) { 1062 for(var i = 0 ; i < numberOfPieces ; ++i) { 1063 if((otherRepeater.itemAt(i).parentIndex != -1) && (otherRepeater.itemAt(i).visible)) 1064 permittedIndex.push(i) 1065 } 1066 } 1067 1068 for(var index = 0 ; index < permittedIndex.length ; ++index) { 1069 var i = permittedIndex[index] 1070 var piece = otherRepeater.itemAt(i) 1071 1072 if(piece.visible) { 1073 if(piece.pieceParent.leftPoint && piece.pieceParent.leftPoint.state == "EMPTY") { 1074 if(checkMill(piece.pieceParent.leftPoint.index, piece.state, "left")) { 1075 return i 1076 } 1077 } 1078 if(piece.pieceParent.rightPoint && piece.pieceParent.rightPoint.state == "EMPTY") { 1079 if(checkMill(piece.pieceParent.rightPoint.index, piece.state, "right")) { 1080 return i 1081 } 1082 } 1083 if(piece.pieceParent.upperPoint && piece.pieceParent.upperPoint.state == "EMPTY") { 1084 if(checkMill(piece.pieceParent.upperPoint.index, piece.state, "upper")) { 1085 return i 1086 } 1087 } 1088 if(piece.pieceParent.lowerPoint && piece.pieceParent.lowerPoint.state == "EMPTY") { 1089 if(checkMill(piece.pieceParent.lowerPoint.index, piece.state, "lower")) { 1090 return i 1091 } 1092 } 1093 } 1094 } 1095 1096 return getFirstPhaseRemoveIndex() 1097 } 1098 1099 // removePiece(index) called by Piece when items.pieceBeingRemoved is true 1100 function removePiece(index) { 1101 otherRepeater.itemAt(index).visible = false 1102 // Decrease number of pieces of other player by 1 1103 if(items.turn % 2) 1104 numberOfFirstPieces -- 1105 else 1106 numberOfSecondPieces -- 1107 if(items.firstPhase) { 1108 items.instructionTxt = qsTr("Place a piece") 1109 continueGame() 1110 } 1111 else 1112 checkGameWon() 1113 } 1114 1115 function removePieceSelected(index) { 1116 otherRepeater.itemAt(index).pieceParent.state = items.firstPhase ? "AVAILABLE" : "EMPTY" 1117 for(var i = 0 ; i < numberOfPieces ; ++i) 1118 otherRepeater.itemAt(i).canBeRemoved = false 1119 } 1120 1121 function checkGameWon() { 1122 // Check if other player can mover or not 1123 var flag = true; 1124 for (var i = 0 ; i < numberOfPieces ; ++i) { 1125 var piece = otherRepeater.itemAt(i) 1126 if(piece.visible) { 1127 if((piece.pieceParent.leftPoint && piece.pieceParent.leftPoint.state == "EMPTY") || 1128 (piece.pieceParent.rightPoint && piece.pieceParent.rightPoint.state == "EMPTY") || 1129 (piece.pieceParent.upperPoint && piece.pieceParent.upperPoint.state == "EMPTY") || 1130 (piece.pieceParent.lowerPoint && piece.pieceParent.lowerPoint.state == "EMPTY")) { 1131 flag = false 1132 break 1133 } 1134 } 1135 } 1136 1137 if(((numberOfSecondPieces < 3 && !items.playSecond) || (numberOfFirstPieces < 3 && items.playSecond)) || 1138 (flag && ((currentPiece.state == "1" && !items.playSecond && numberOfSecondPieces > 3) || 1139 (currentPiece.state == "2" && items.playSecond && numberOfFirstPieces > 3)))) { 1140 items.gameDone = true 1141 items.player1score.win(); 1142 items.player2score.endTurn(); 1143 items.instructionTxt = qsTr("Congratulations") 1144 items.bonus.good("flower") 1145 if(twoPlayer) { 1146 items.instructionTxt = qsTr("Congratulations Player 1") 1147 } 1148 } 1149 else if(((numberOfFirstPieces < 3 && !items.playSecond) || (numberOfSecondPieces < 3 && items.playSecond)) || 1150 (flag && ((currentPiece.state == "2" && !items.playSecond && numberOfFirstPieces > 3) || 1151 (currentPiece.state == "1" && items.playSecond && numberOfSecondPieces > 3)))) { 1152 items.gameDone = true 1153 items.player2score.win(); 1154 items.player1score.endTurn(); 1155 if(twoPlayer) { 1156 items.bonus.good("flower") 1157 items.instructionTxt = qsTr("Congratulations Player 2") 1158 } 1159 else { 1160 items.instructionTxt = qsTr("Try again") 1161 items.bonus.bad("tux") 1162 } 1163 } 1164 else { 1165 // Continue the game 1166 items.instructionTxt = qsTr("Move a piece") 1167 continueGame() 1168 } 1169 } 1170 1171 function getBoard() { 1172 var board = [] 1173 for (var i = 0 ; i < numberOfDragPoints ; ++i) { 1174 if(items.dragPoints.itemAt(i).state == "1") { 1175 if(items.playSecond) 1176 board.push(2) 1177 else 1178 board.push(1) 1179 } 1180 else if(items.dragPoints.itemAt(i).state == "2") { 1181 if(items.playSecond) 1182 board.push(1) 1183 else 1184 board.push(2) 1185 } 1186 else 1187 board.push(0) 1188 } 1189 return board 1190 } 1191 1192 function alphabeta(depth, alpha, beta, player, board, boardPiecesLeft, mill) { 1193 1194 var firstPhase = boardPiecesLeft != 0 1195 var values = getValue(board, firstPhase, player) 1196 var value = values.value 1197 var myToBeMill = 0 1198 var oppToBeMill = 0 1199 1200 if(value != 9000 && value != -9000 && depth == 0) { 1201 var lost = -8500 1202 var win = 8500 1203 var toBeMill = 1.8 1204 var myMillReachable = false 1205 var oppMillReachable = false 1206 var playerPieces = values.playerPieces 1207 var computerPieces = values.computerPieces 1208 1209 for (var i = 0 ; i < numberOfDragPoints ; ++i) { 1210 if (board[i] == 0) { 1211 if(checkMillBoardPossible(board, i, 2, firstPhase, computerPieces)) { 1212 myToBeMill++ 1213 if(positionReachable(board, i, 1, firstPhase, playerPieces)) 1214 myMillReachable = true 1215 } 1216 if(checkMillBoardPossible(board, i, 1, firstPhase, playerPieces)) { 1217 oppToBeMill++ 1218 if(positionReachable(board, i, 2, firstPhase, computerPieces)) 1219 oppMillReachable = true 1220 } 1221 } 1222 } 1223 1224 if(myToBeMill > 2 && playerPieces == 4 && !firstPhase && (mill == false || player == 2)){ 1225 value: win - 50 1226 } 1227 else if(oppToBeMill > 2 && computerPieces == 4 && !firstPhase && (mill == false || player == 1)) { 1228 value: lost + 50 1229 } 1230 else { 1231 if(myToBeMill > 0 && myMillReachable && player == 1 && ((playerPieces != 3 && 1232 !firstPhase) || firstPhase)) 1233 myToBeMill-- 1234 if(oppToBeMill > 0 && oppMillReachable && player == 2 && ((computerPieces != 3 && 1235 !firstPhase) || firstPhase)) 1236 oppToBeMill-- 1237 1238 if(myToBeMill > 0 && playerPieces == 3 && player == 2 && !firstPhase){ 1239 value = win 1240 } 1241 else if(oppToBeMill > 0 && computerPieces == 3 && player == 1 && !firstPhase){ 1242 value = lost 1243 } 1244 else if(myToBeMill > 1 && playerPieces == 3 && player == 1 && !firstPhase && 1245 !mill){ 1246 value = win - 25 1247 } 1248 else if(oppToBeMill > 1 && computerPieces == 3 && player == 2 && !firstPhase && 1249 !mill){ 1250 value = lost + 25 1251 } 1252 else 1253 value += toBeMill * (myToBeMill - oppToBeMill) 1254 } 1255 1256 if(mill && depth == 0){// && value < 8000 && value > -8000) { 1257 if(player == 2 && playerPieces == 3 && !firstPhase) 1258 value = 9000 1259 else if(player == 1 && computerPieces == 3 && !firstPhase) 1260 value = -9000 1261 else if(player == 2) { 1262 if(oppToBeMill == 0) 1263 value += 1.4 1264 else if(oppToBeMill == 1) 1265 value += 3.2 1266 else 1267 value += 4.8 1268 } 1269 else { 1270 if(myToBeMill == 0) 1271 value -= 1.4 1272 else if(myToBeMill == 1) 1273 value -= 3.2 1274 else 1275 value -= 4.8 1276 } 1277 } 1278 1279 if(mill && depth == 1 && !firstPhase && player == 2 && playerPieces == 4 1280 && oppToBeMill > 0) 1281 return value + 3.2 1282 1283 value = Math.round(value * 1000) / 1000 1284 } 1285 1286 if(depth == 0 || ((value == 9000 || value < -8000) && depth != depthMax)) { 1287 return value 1288 } 1289 1290 if(player == 2) { 1291 var scores = [] 1292 if(mill) { 1293 var removableIndex = getRemovableIndexFromBoard(board, 1) 1294 var found = false 1295 for(var i = 0 ; i < removableIndex.length ; ++i) { 1296 board[removableIndex[i]] = 0 1297 var newAlpha = alphabeta(depth - 1, alpha, beta, 1, board, boardPiecesLeft, false) 1298 board[removableIndex[i]] = 1 1299 if(newAlpha >= alpha) { 1300 found = true 1301 alpha = newAlpha 1302 scores[i] = alpha 1303 } 1304 if(beta < alpha) break 1305 } 1306 if(depth == depthMax) { 1307 var max = -9000; 1308 for(var i = 0; i < scores.length; i++) { 1309 if(scores[i] != undefined && scores[i] > max) 1310 max = scores[i] 1311 } 1312 var index = [] 1313 for(var i = 0; i < scores.length; i++) { 1314 if(scores[i] != undefined && scores[i] == max) 1315 index.push(i) 1316 } 1317 var randno = Math.floor((Math.random() * index.length)) 1318 return removableIndex[index[randno]] 1319 } 1320 if(found) 1321 return alpha 1322 else 1323 return alpha - 1000 1324 } 1325 else if(firstPhase) { 1326 var scores = [] 1327 var moves = generateMove(board, 2, 0, true) 1328 for(var i = 0 ; i < moves.length ; ++i) { 1329 var move = moves[i] 1330 board[move] = 2 1331 boardPiecesLeft-- 1332 var newAlpha 1333 if(checkMillBoard(board, move) != 0) 1334 newAlpha = alphabeta(depth - 1, alpha, beta, 2, board, boardPiecesLeft, true) 1335 else 1336 newAlpha = alphabeta(depth - 1, alpha, beta, 1, board, boardPiecesLeft, false) 1337 boardPiecesLeft++ 1338 board[move] = 0 1339 if(newAlpha >= alpha) { 1340 alpha = newAlpha 1341 scores[i] = alpha 1342 } 1343 if(beta < alpha) break 1344 } 1345 if(depth == depthMax) { 1346 var max = -9000; 1347 for(var i = 0; i < scores.length; i++) { 1348 if(scores[i] != undefined && scores[i] > max) 1349 max = scores[i] 1350 } 1351 var index = [] 1352 for(var i = 0; i < scores.length; i++) { 1353 if(scores[i] != undefined && scores[i] == max) 1354 index.push(i) 1355 } 1356 var randno = Math.floor((Math.random() * index.length)) 1357 return moves[index[randno]] 1358 } 1359 return alpha 1360 } 1361 else { 1362 var computerPointsIndex = [] 1363 for (var i = 0 ; i < numberOfDragPoints ; ++i) { 1364 if(board[i] == 2) 1365 computerPointsIndex.push(i) 1366 } 1367 var scores = [] 1368 for (var i = 0 ; i < computerPointsIndex.length ; ++i) { 1369 var computerPoint = computerPointsIndex[i] 1370 var moves = generateMove(board, 2, computerPoint, false) 1371 scores[i] = [] 1372 for(var j = 0 ; j < moves.length ; ++j) { 1373 var move = moves[j] 1374 board[computerPoint] = 0 1375 board[move] = 2 1376 var newAlpha 1377 if(checkMillBoard(board, move) != 0) 1378 newAlpha = alphabeta(depth - 1, alpha, beta, 2, board, boardPiecesLeft, true) 1379 else 1380 newAlpha = alphabeta(depth - 1, alpha, beta, 1, board, boardPiecesLeft, false) 1381 board[computerPoint] = 2 1382 board[move] = 0 1383 if(newAlpha >= alpha) { 1384 alpha = newAlpha 1385 scores[i][move] = alpha 1386 } 1387 if(beta < alpha) break 1388 } 1389 if(beta < alpha) break 1390 } 1391 if(depth == depthMax) { 1392 var max = -9000; 1393 for(var i = 0; i < scores.length; i++) { 1394 for(var j = 0 ; j < scores[i].length ; j++) { 1395 if(scores[i][j] != undefined) { 1396 if(scores[i][j] > max) { 1397 max = scores[i][j] 1398 } 1399 } 1400 } 1401 } 1402 var moveIndex = [] 1403 for(var i = 0; i < scores.length; i++) { 1404 for(var j = 0 ; j < scores[i].length ; j++) { 1405 if(scores[i][j] != undefined && scores[i][j] == max) { 1406 var index = [] 1407 index[0] = computerPointsIndex[i] 1408 index[1] = j 1409 moveIndex.push(index) 1410 } 1411 } 1412 } 1413 var randno = Math.floor((Math.random() * moveIndex.length)) 1414 return moveIndex[randno] 1415 } 1416 return alpha 1417 } 1418 } 1419 else { 1420 if(mill) { 1421 var removableIndex = getRemovableIndexFromBoard(board, 2) 1422 for(var i = 0 ; i < removableIndex.length ; ++i) { 1423 board[removableIndex[i]] = 0 1424 if(playerPieces == 3 && computerPieces == 4 && !firstPhase) 1425 beta = Math.min(beta, alphabeta(depth, alpha, beta, 2, board, boardPiecesLeft, false)) 1426 board[removableIndex[i]] = 2 1427 if(beta < alpha) break 1428 } 1429 return beta 1430 } 1431 else if(boardPiecesLeft != 0) { // First Phase 1432 var moves = generateMove(board, 1, 0, true) 1433 for(var i = 0 ; i < moves.length ; ++i) { 1434 var move = moves[i] 1435 board[move] = 1 1436 boardPiecesLeft-- 1437 if(checkMillBoard(board, move) != 0) 1438 beta = Math.min(beta, alphabeta(depth - 1, alpha, beta, 1, board, boardPiecesLeft, true)) 1439 else 1440 beta = Math.min(beta, alphabeta(depth - 1, alpha, beta, 2, board, boardPiecesLeft, false)) 1441 boardPiecesLeft++ 1442 board[move] = 0 1443 if(beta < alpha) break 1444 } 1445 return beta 1446 } 1447 else { 1448 var playerPointsIndex = [] 1449 for (var i = 0 ; i < numberOfDragPoints ; ++i) { 1450 if(board[i] == 1) 1451 playerPointsIndex.push(i) 1452 } 1453 for (var i = 0 ; i < playerPointsIndex.length ; ++i) { 1454 var playerPoint = playerPointsIndex[i] 1455 var moves = generateMove(board, 1, playerPoint, false) 1456 for(var j = 0 ; j < moves.length ; ++j) { 1457 var move = moves[j] 1458 board[playerPoint] = 0 1459 board[move] = 1 1460 if(checkMillBoard(board, move) != 0) 1461 beta = Math.min(beta, alphabeta(depth - 1, alpha, beta, 1, board, boardPiecesLeft, true)) 1462 else 1463 beta = Math.min(beta, alphabeta(depth - 1, alpha, beta, 2, board, boardPiecesLeft, false)) 1464 board[playerPoint] = 1 1465 board[move] = 0 1466 if(beta < alpha) break 1467 } 1468 if(beta < alpha) break 1469 } 1470 return beta 1471 } 1472 } 1473 } 1474 1475 function getRemovableIndexFromBoard(board, state) { 1476 1477 var index = [] 1478 for (var i = 0 ; i < numberOfDragPoints ; ++i) { 1479 if (board[i] == state && checkMillBoard(board, i) == 0) 1480 index.push(i) 1481 } 1482 if(index.length == 0) { 1483 for (var i = 0 ; i < numberOfDragPoints ; ++i) { 1484 if (board[i] == state) 1485 index.push(i) 1486 } 1487 } 1488 return index 1489 } 1490 1491 function getValue(board, firstPhase, player) { 1492 1493 var value = 0.0 1494 var material = 1.0 1495 var freedom = 0.2 1496 var mills = 0.8 1497 var lost = -8500 1498 var win = 8500 1499 var toBeMill = 1.8 1500 1501 // ========== material ========== 1502 1503 var computerPieces = getNumberOfPieces(board, 2) 1504 var playerPieces = getNumberOfPieces(board, 1) 1505 1506 if (computerPieces < 3 && !firstPhase) { 1507 return {value: lost - 500} 1508 } 1509 1510 if (playerPieces < 3 && !firstPhase) { 1511 return {value: win + 500} 1512 } 1513 1514 value += material * (computerPieces - playerPieces) 1515 1516 // ========== mills ========== 1517 1518 var computerMills = 0 1519 var playerMills = 0 1520 var computerMillsIndex = [] 1521 var playerMillsIndex = [] 1522 1523 for (var i = 0 ; i < numberOfDragPoints ; ++i) { 1524 if(computerMillsIndex.indexOf(i) == -1 && board[i] == 2) { 1525 computerMills += checkMillBoard(board, i, computerMillsIndex) 1526 } 1527 else if(playerMillsIndex.indexOf(i) == -1 && board[i] == 1) { 1528 playerMills += checkMillBoard(board, i, playerMillsIndex) 1529 } 1530 } 1531 value += mills * (computerMills - playerMills) 1532 1533 // ========== freedom ========== 1534 if(playerPieces != 3 || computerPieces != 3 || firstPhase) { 1535 var myFreedom = 0 1536 var oppFreedom = 0 1537 for (var i = 0 ; i < numberOfDragPoints ; ++i) { 1538 if (board[i] == 2) 1539 myFreedom += positionAchievable(board, i, computerPieces, firstPhase) 1540 else if (board[i] == 1) 1541 oppFreedom += positionAchievable(board, i, playerPieces, firstPhase) 1542 } 1543 1544 if (myFreedom == 0 && !firstPhase){ 1545 return {value: lost, computerPieces: computerPieces, playerPieces: playerPieces} 1546 } 1547 if (oppFreedom == 0 && !firstPhase){ 1548 return {value: win + 500, computerPieces: computerPieces, playerPieces: playerPieces} 1549 } 1550 1551 if(((computerPieces > 3 && playerPieces == 3 && computerPieces < 6) || 1552 (playerMills > 0 && playerPieces == 4)) && !firstPhase) 1553 freedom = 0 1554 value += freedom * (myFreedom - oppFreedom) 1555 } 1556 value = Math.round(value * 1000) / 1000 1557 1558 return {value: value, computerPieces: computerPieces, playerPieces: playerPieces} 1559 } 1560 1561 function getNumberOfPieces(board, state) { 1562 var no = 0 1563 for (var i = 0 ; i < numberOfDragPoints ; ++ i) { 1564 if (board[i] == state) 1565 no ++ 1566 } 1567 return no 1568 } 1569 1570 function positionAchievable(board, index, noOfBoardPieces, firstPhase) { 1571 var positions = 0 1572 if(noOfBoardPieces == 3 && !firstPhase) { 1573 for (var i = 0 ; i < numberOfDragPoints ; ++ i) { 1574 if (board[i] == 0) 1575 positions ++ 1576 } 1577 } 1578 else { 1579 var point = items.dragPoints.itemAt(index) 1580 if(point.leftPoint && board[point.leftPoint.index] == 0) 1581 positions ++ 1582 if(point.rightPoint && board[point.rightPoint.index] == 0) 1583 positions ++ 1584 if(point.upperPoint && board[point.upperPoint.index] == 0) 1585 positions ++ 1586 if(point.lowerPoint && board[point.lowerPoint.index] == 0) 1587 positions ++ 1588 } 1589 return positions 1590 } 1591 1592 function positionReachable(board, index, state, firstPhase, noOfBoardPieces) { 1593 if(noOfBoardPieces == 3 || firstPhase) 1594 return true 1595 else { 1596 var point = items.dragPoints.itemAt(index) 1597 if(point.leftPoint && board[point.leftPoint.index] == state) 1598 return true 1599 if(point.rightPoint && board[point.rightPoint.index] == state) 1600 return true 1601 if(point.upperPoint && board[point.upperPoint.index] == state) 1602 return true 1603 if(point.lowerPoint && board[point.lowerPoint.index] == state) 1604 return true 1605 return false 1606 } 1607 } 1608 1609 function checkMillBoard(board, index, millsIndex) { 1610 var point = items.dragPoints.itemAt(index) 1611 var state = board[index] 1612 var mills = 0 1613 if (millsIndex == undefined) 1614 millsIndex = [] 1615 1616 if(point.leftPoint && point.leftPoint.leftPoint && state == board[point.leftPoint.index] 1617 && state == board[point.leftPoint.leftPoint.index]) { 1618 mills ++ 1619 millsIndex.push(point.leftPoint.index) 1620 millsIndex.push(point.leftPoint.leftPoint.index) 1621 } 1622 if(point.upperPoint && point.upperPoint.upperPoint && state == board[point.upperPoint.index] 1623 && state == board[point.upperPoint.upperPoint.index]) { 1624 mills ++ 1625 millsIndex.push(point.upperPoint.index) 1626 millsIndex.push(point.upperPoint.upperPoint.index) 1627 } 1628 if(point.rightPoint && point.rightPoint.rightPoint && state == board[point.rightPoint.index] 1629 && state == board[point.rightPoint.rightPoint.index]) { 1630 mills ++ 1631 millsIndex.push(point.rightPoint.index) 1632 millsIndex.push(point.rightPoint.rightPoint.index) 1633 } 1634 if(point.lowerPoint && point.lowerPoint.lowerPoint && state == board[point.lowerPoint.index] 1635 && state == board[point.lowerPoint.lowerPoint.index]) { 1636 mills ++ 1637 millsIndex.push(point.lowerPoint.index) 1638 millsIndex.push(point.lowerPoint.lowerPoint.index) 1639 } 1640 if(point.lowerPoint && point.upperPoint && state == board[point.lowerPoint.index] 1641 && state == board[point.upperPoint.index]) { 1642 mills ++ 1643 millsIndex.push(point.lowerPoint.index) 1644 millsIndex.push(point.upperPoint.index) 1645 } 1646 if(point.leftPoint && point.rightPoint && state == board[point.leftPoint.index] 1647 && state == board[point.rightPoint.index]) { 1648 mills ++ 1649 millsIndex.push(point.rightPoint.index) 1650 millsIndex.push(point.leftPoint.index) 1651 } 1652 return mills 1653 } 1654 1655 function checkMillBoardPossible(board, index, state, firstPhase, pieces) { 1656 1657 var freeMove = pieces == 3 || firstPhase 1658 var point = items.dragPoints.itemAt(index) 1659 1660 if(point.leftPoint && point.leftPoint.leftPoint) { 1661 if(state == board[point.leftPoint.index] && state == board[point.leftPoint.leftPoint.index]) { 1662 if((point.upperPoint && state == board[point.upperPoint.index]) || 1663 (point.lowerPoint && state == board[point.lowerPoint.index]) || freeMove) 1664 return true; 1665 } 1666 } 1667 if(point.upperPoint && point.upperPoint.upperPoint) { 1668 if(state == board[point.upperPoint.index] && state == board[point.upperPoint.upperPoint.index]) { 1669 if((point.leftPoint && state == board[point.leftPoint.index]) || 1670 (point.rightPoint && state == board[point.rightPoint.index]) || freeMove) 1671 return true; 1672 } 1673 } 1674 if(point.rightPoint && point.rightPoint.rightPoint) { 1675 if(state == board[point.rightPoint.index] && state == board[point.rightPoint.rightPoint.index]) { 1676 if((point.upperPoint && state == board[point.upperPoint.index]) || 1677 (point.lowerPoint && state == board[point.lowerPoint.index]) || freeMove) 1678 return true; 1679 } 1680 } 1681 if(point.lowerPoint && point.lowerPoint.lowerPoint) { 1682 if(state == board[point.lowerPoint.index] && state == board[point.lowerPoint.lowerPoint.index]) { 1683 if((point.leftPoint && state == board[point.leftPoint.index]) || 1684 (point.rightPoint && state == board[point.rightPoint.index]) || freeMove) 1685 return true; 1686 } 1687 } 1688 if(point.lowerPoint && point.upperPoint) { 1689 if(state == board[point.lowerPoint.index] && state == board[point.upperPoint.index]) { 1690 if((point.leftPoint && state == board[point.leftPoint.index]) || 1691 (point.rightPoint && state == board[point.rightPoint.index]) || freeMove) 1692 return true; 1693 } 1694 } 1695 if(point.leftPoint && point.rightPoint) { 1696 if(state == board[point.leftPoint.index] && state == board[point.rightPoint.index]) { 1697 if((point.upperPoint && state == board[point.upperPoint.index]) || 1698 (point.lowerPoint && state == board[point.lowerPoint.index]) || freeMove) 1699 return true; 1700 } 1701 } 1702 return false; 1703 } 1704 1705 function generateMove(board, state, index, firstPhase) { 1706 var moves = [] 1707 if(firstPhase || getNumberOfPieces(board, state) == 3) { 1708 for (var i = 0 ; i < numberOfDragPoints ; ++i) { 1709 if (board[i] == 0) 1710 moves.push(i) 1711 } 1712 } 1713 else { 1714 var point = items.dragPoints.itemAt(index) 1715 if(point.leftPoint && board[point.leftPoint.index] == 0) 1716 moves.push(point.leftPoint.index) 1717 if(point.rightPoint && board[point.rightPoint.index] == 0) 1718 moves.push(point.rightPoint.index) 1719 if(point.upperPoint && board[point.upperPoint.index] == 0) 1720 moves.push(point.upperPoint.index) 1721 if(point.lowerPoint && board[point.lowerPoint.index] == 0) 1722 moves.push(point.lowerPoint.index) 1723 } 1724 return moves 1725 } 1726 1727