Advertisement
Guest User

Untitled

a guest
Apr 30th, 2017
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.40 KB | None | 0 0
  1. // Import the game logic script from the root file
  2. importScripts('gamelogic.js');
  3.  
  4. /**
  5. * On a message event as running via web worker.
  6. * @param {Object} event The event details
  7. * @param {Array} event.data The array of data sent with the request
  8. * @param {String} event.data[0] The event command
  9. * @param {String} event.data[1] The game board
  10. * @param {Object} event.data[2] The Human users ships
  11. * @param {Double} event.data[3] The AI Skill level
  12. * @param {Boolean} event.data[4] Whether it is the first game or not
  13. */
  14. onmessage = function(event) {
  15. // Extract the command and parameters
  16. let command = event.data[0];
  17. let board = event.data[1], ships = event.data[2], skillLevel = event.data[3], firstGame = event.data[4];
  18.  
  19. // Switch the command that was sent
  20. switch(command) {
  21. // Move command requested
  22. case 'move':
  23. // Get and post the move back to the main thread
  24. //setTimeout(function() {
  25. postMessage({move: aiMove(board, ships, skillLevel, firstGame)});
  26. //}, 350);
  27.  
  28. break;
  29.  
  30. // If a ship placement is requested
  31. case 'getBoard':
  32. // Post the ships back to the user
  33. postMessage({ships: getAIShipPlacement()});
  34. break;
  35.  
  36. // Chat command requested
  37. case 'chat':
  38. // Get a chat message
  39. let message = aiChat(board, skillLevel, firstGame);
  40.  
  41. // If a chat message was returned, post it
  42. if(message != undefined && message != '') {
  43. postMessage({message: message});
  44. }
  45.  
  46. break;
  47. }
  48. }
  49.  
  50. //skillLevel is the sliding scale, number between 1 and 10
  51. //board is the current board
  52. function aiMove(board, ships, skillLevel, firstGame) {
  53. let difficulty = skillLevel*10;
  54. let availableMoves;
  55. let move;
  56. let pick;
  57. let random;
  58. let huntAbility = false;
  59. let advancedHuntMode = false;
  60. let advancedSearchMode = false;
  61. let cheatMode = false;
  62. let probablity;
  63.  
  64. switch (difficulty){
  65. case 0:
  66. //All features are false.
  67. break;
  68. case 1:
  69. huntAbility = true;
  70. probablity = 0.6;
  71.  
  72. break;
  73. case 2:
  74. huntAbility = true;
  75. probablity = 0.4;
  76. break;
  77. case 3:
  78. huntAbility = true;
  79. probablity = 0.2;
  80. break;
  81. case 4:
  82. huntAbility = true;
  83. advancedSearchMode = true;
  84. probablity = 0.6;
  85.  
  86. break;
  87. case 5:
  88. huntAbility = true;
  89. advancedSearchMode = true;
  90. probablity = 0.4;
  91.  
  92. break;
  93. case 6:
  94. huntAbility = true;
  95. advancedSearchMode = true;
  96. probablity = 0.2;
  97.  
  98. break;
  99. case 7:
  100. huntAbility = true;
  101. advancedSearchMode = true;
  102. advancedHuntMode = true;
  103. probablity = 0.6;
  104.  
  105. break;
  106. case 8:
  107. huntAbility = true;
  108. advancedSearchMode = true;
  109. advancedHuntMode = true;
  110. probablity = 0.4;
  111.  
  112. break;
  113. case 9:
  114. huntAbility = true;
  115. advancedSearchMode = true;
  116. advancedHuntMode = true;
  117. probablity = 0.2;
  118.  
  119. break;
  120. case 10:
  121. huntAbility = true;
  122. advancedSearchMode = true;
  123. advancedHuntMode = true;
  124. cheatMode = true;
  125. probablity = 0.1
  126. }
  127.  
  128. //Generate a random number between 0 and 1
  129. random = Math.random();
  130.  
  131. //Determine whether to use huntAbility for levels 1 - 3.
  132. if(difficulty > 0 && difficulty < 4){
  133. if(random <= probablity){
  134. huntAbility = false;
  135. }
  136. }
  137.  
  138. //Determine whether to use advanced search mode for levels 4 - 6
  139. if(difficulty > 3 && difficulty < 7){
  140. if(random <= probablity){
  141. advancedSearchMode = false;
  142. }
  143. }
  144.  
  145. //Determine whether to use advanced hunt mode for levels 7 - 9
  146. if(difficulty > 6 && difficulty < 10){
  147. if(random <= probablity){
  148. advancedHuntMode = false;
  149. }
  150. }
  151.  
  152. //Determine whether to use the cheat mode for level 10.
  153. if(cheatMode == true && random <= probablity){
  154. cheatMode = true;
  155. }
  156. else{
  157. cheatMode = false;
  158. }
  159. console.log("Difficulty: " + difficulty + " Hunt Ability: " + huntAbility + " Advanced Search Mode: " + advancedSearchMode + " Advanced Hunt Mode: " + advancedHuntMode + " Cheat Mode: " + cheatMode);
  160. //Determine whether there are any hits on the board, hence returning true for huntmode.
  161. huntMode = checkHits(board);
  162. //Hunt modes.
  163. //If the there is a hit and the AI has hunt ability activated. Begin a hunt for the ship.
  164. if(huntMode == true && huntAbility == true){
  165. //If the AI has advanced hunt mode activated, use the advanced find hit method.
  166. if(advancedHuntMode == true){
  167. move = advancedFindHits(board);
  168. return{row: move.row, col: move.col};
  169. }
  170. else{
  171. //Otherwise use the standard find hit method to return moves to randomly choose from.
  172. availableMoves = findHits(board);
  173. }
  174. }
  175. //Search modes.
  176. else{
  177. //If cheatMode is activated get an array of cheat moves.
  178. if(cheatMode == true){
  179. availableMoves = getCheatMoves(board);
  180. }
  181. //If advanced search mode is activated use the advanced get moves method.
  182. else if(advancedSearchMode == true){
  183. availableMoves = advancedGetAvailableMoves(board);
  184. }
  185. //Otherwise use the standard get moves method.
  186. else{
  187. availableMoves = getAvailableMoves(board);
  188. }
  189. }
  190. //Randomly pick a move from the available moves.
  191. pick = Math.floor(Math.random()* availableMoves.length);
  192. move = availableMoves[pick];
  193. //Return the move coordinates.
  194. return {row: move.row , col: move.col};
  195.  
  196. }
  197.  
  198. /*--------------- Search Methods ---------------*/
  199. //Methods to return moves for the AI to take.
  200.  
  201. //Standard method to return an array of all the potential moves the AI can make.
  202. function getAvailableMoves(board){
  203. //Array to store move objects.
  204. let availableMoves = [];
  205. //Traverse the board to access each cell.
  206. for(let i = 0; i < 10; i++){
  207. for(let j = 0; j < 10; j++){
  208. //If the board position is available for a placement, push it to the moves array.
  209. if(board[i][j].value == 's' || board[i][j].value == ''){
  210. availableMoves.push({row: i, col: j});
  211. }
  212. }
  213. }
  214. return availableMoves;
  215. }
  216.  
  217. //Advanced version of getAvailableMoves method.
  218. //This method returns availableMoves where the parity of the row and column index is the same.
  219. //Meaning a cross patern will be used to search the board, hence making it more likely to get a hit.
  220. function advancedGetAvailableMoves(board){
  221. //Array to store move objects.
  222. let availableMoves = [];
  223. //Traverse the board to access each cell.
  224. for(let i = 0; i < 10; i++){
  225. for(let j = 0; j < 10; j++){
  226. //If the row and column indexes are both even.
  227. if(i%2 == 0 && j%2 == 0){
  228. //If the board position is available for a placement, push it to the moves array.
  229. if(board[i][j].value == 's' || board[i][j].value == ''){
  230. availableMoves.push({row: i, col: j});
  231. }
  232. }
  233. //If the row and column indexes are both odd.
  234. else if(i%2 != 0 && j%2 != 0){
  235. //If the board position is available for a placement, push it to the moves array.
  236. if(board[i][j].value == 's' || board[i][j].value == ''){
  237. availableMoves.push({row: i, col: j});
  238. }
  239. }
  240.  
  241. }
  242. }
  243. //Array of moves is returned.
  244. return availableMoves;
  245. }
  246.  
  247. //Cheat Mode.
  248. //This method is for the top difficulty.
  249. //Returns all the positions with ship locations.
  250. function getCheatMoves(board){
  251. //Array to store move objects.
  252. let availableMoves = [];
  253. //Traverse the board to access each cell.
  254. for(let i = 0; i < 10; i++){
  255. for(let j = 0; j < 10; j++){
  256. //If there is a ship in the position, push it to the moves array.
  257. if(board[i][j].value == 's'){
  258. availableMoves.push({row: i, col: j});
  259. }
  260. }
  261. }
  262. //Array of moves is returned.
  263. return availableMoves;
  264. }
  265.  
  266.  
  267.  
  268. /*--------------- Hunting Methods ---------------*/
  269. //Methods to determine if there is a hit, and use that information to destroy the entire ship.
  270.  
  271. //Method to return whether it is necessary to enter hunt mode.
  272. function checkHits(board){
  273. //Traverse the board to access each cell.
  274. for(let i = 0; i < 10; i++){
  275. for(let j = 0; j < 10; j++){
  276. //IF there is a hit return true to begin hunt mode.
  277. if(board[i][j].value == 'h'){
  278. return true;
  279. }
  280. }
  281. }
  282. //Otherwise return false to continue search mode.
  283. return false;
  284.  
  285. }
  286.  
  287. //Method to search the cells around a hit.
  288. function findHits(board){
  289. //Array to store move objects.
  290. let availableMoves = [];
  291. //Traverse the board to access each cell.
  292. for(let i = 0; i < 10; i++){
  293. for(let j = 0; j < 10; j++){
  294. //If there is a hit cell, search its surounding cells.
  295. if(board[i][j].value == 'h'){
  296. //If the current row is not the top row.
  297. if(i != 0){
  298. //Check if the position above the cell is available for a move.
  299. if(board[i-1][j].value == '' || board[i-1][j].value == 's'){
  300. //Push move to array.
  301. availableMoves.push({row: i - 1, col: j});
  302. }
  303. }
  304. //If the current the row is not the bottom row.
  305. if(i != 9){
  306. //Check if the position below the cell is available for a move.
  307. if(board[i+1][j].value == '' || board[i+1][j].value == 's'){
  308. //Push move to array.
  309. availableMoves.push({row: i + 1, col: j});
  310. }
  311. }
  312. //If the current column is not the far left column.
  313. if(j != 0){
  314. //Check if the position left of the cell is available for a move.
  315. if(board[i][j-1].value == '' || board[i][j-1].value == 's'){
  316. //Push move to array.
  317. availableMoves.push({row: i, col: j - 1});
  318. }
  319. }
  320. //If the current column is not the far right column.
  321. if(j != 9){
  322. //Check if the position right of the cell is available for a move.
  323. if(board[i][j+1].value == '' || board[i][j+1].value == 's'){
  324. //Push move to array.
  325. availableMoves.push({row: i, col: j + 1});
  326. }
  327.  
  328. }
  329.  
  330. }
  331. }
  332. }
  333. //Return the array of moves.
  334. return availableMoves;
  335. }
  336.  
  337.  
  338. //Advanced find hit mode for higher difficulties - sinks ships faster than normal version.
  339. function advancedFindHits(board){
  340. let informedMoves = [];
  341. let vertical = false;
  342. let horizontal = false;
  343.  
  344. for(let i = 0; i < 10; i++){
  345. for(let j = 0; j < 10; j++){
  346. if(board[i][j].value == 'h'){
  347. if(i != 0){
  348. if(board[i-1][j].value == 'h'){
  349. vertical = true;
  350. }
  351. }
  352. if(i != 9){
  353. if(board[i+1][j].value == 'h'){
  354. vertical = true;
  355. }
  356. }
  357.  
  358. if(j != 0){
  359. if(board[i][j-1].value == 'h'){
  360. horizontal = true;
  361. }
  362. }
  363. if(j != 9){
  364. if(board[i][j+1].value == 'h'){
  365. horizontal = true;
  366. }
  367. }
  368.  
  369. //Select a surounding cell.
  370. //Above.
  371. if(horizontal == false){
  372. if(i != 0){
  373. if(board[i-1][j].value == '' || board[i-1][j].value == 's'){
  374. return {row: i - 1, col: j};
  375. }
  376.  
  377. if(board[i-1][j].value == 'h'){
  378. if(i - 1 != 0){
  379. if(board[i-1][j].value == '' || board[i-1][j].value == 's'){
  380. return {row: i - 2, col: j};
  381. }
  382. }
  383. }
  384. }
  385.  
  386. if(i != 9){
  387. if(board[i+1][j].value == '' || board[i+1][j].value == 's'){
  388. return {row: i + 1, col: j};
  389. }
  390.  
  391. if(board[i+1][j].value == 'h'){
  392. if(i + 1 != 9){
  393. if(board[i+1][j].value == '' || board[i+1][j].value == 's'){
  394. return {row: i + 2, col: j};
  395. }
  396. }
  397. }
  398. }
  399. }
  400. if(vertical == false){
  401. if(j != 0){
  402. if(board[i][j - 1].value == '' || board[i][j-1].value == 's'){
  403. return {row: i, col: j - 1};
  404. }
  405.  
  406. if(board[i][j-1].value == 'h'){
  407. if(j - 1 != 0){
  408. if(board[i][j - 1].value == '' || board[i][j-1].value == 's'){
  409. return {row: i, col: j - 2};
  410. }
  411. }
  412. }
  413. }
  414. if(j != 9){
  415. if(board[i][j + 1].value == '' || board[i][j + 1].value == 's'){
  416. return {row: i, col: j + 1};
  417. }
  418.  
  419. if(board[i][j+1].value == 'h'){
  420. if(j + 1 != 9){
  421. if(board[i][j + 1].value == '' || board[i][j + 1].value == 's'){
  422. return {row: i, col: j + 2};
  423. }
  424. }
  425. }
  426. }
  427. }
  428.  
  429.  
  430. }
  431. }
  432. }
  433.  
  434. //If at this point, moves MUST BE left or right. Loop again and make these moves.
  435. for(let i = 0; i < 10; i++){
  436. for(let j = 0; j < 10; j++){
  437. if(board[i][j].value == 'h'){
  438. if(j != 0){
  439. if(board[i][j - 1].value == '' || board[i][j-1].value == 's'){
  440. return {row: i, col: j - 1};
  441. }
  442.  
  443. if(board[i][j-1].value == 'h'){
  444. if(j - 1 != 0){
  445. if(board[i][j - 1].value == '' || board[i][j-1].value == 's'){
  446. return {row: i, col: j - 2};
  447. }
  448. }
  449. }
  450. }
  451. if(j != 9){
  452. if(board[i][j + 1].value == '' || board[i][j + 1].value == 's'){
  453. return {row: i, col: j + 1};
  454. }
  455.  
  456. if(board[i][j+1].value == 'h'){
  457. if(j + 1 != 9){
  458. if(board[i][j + 1].value == '' || board[i][j + 1].value == 's'){
  459. return {row: i, col: j + 2};
  460. }
  461. }
  462. }
  463. }
  464. }
  465. }
  466. }
  467.  
  468.  
  469.  
  470. //Should never reach this point, but return 0, 0 if is the case.
  471. return ({row: 0, col: 0});
  472. }
  473.  
  474.  
  475.  
  476.  
  477. // returns a board
  478. function getAIShipPlacement() {
  479.  
  480. let pick;
  481. let directions;
  482. let xP;
  483. let yP;
  484. let shipLength;
  485. let directionLimit = 0;
  486. let ships = [];
  487. let tempBoard = [];
  488.  
  489. for(let i=0; i<10; i++) {
  490.  
  491. tempBoard.push([]);
  492.  
  493. for(let j=0; j<10; j++) {
  494. // Push a value of the tile
  495. tempBoard[i].push({value: '', prevMove: '', x: i, y: j});
  496. }
  497.  
  498. }
  499.  
  500. for(let i = 0; i < 5; i++){
  501. switch (i){
  502. case 0:
  503. shipLength = 5;
  504. break;
  505. case 1:
  506. shipLength = 4;
  507. break;
  508. case 2:
  509. shipLength = 3;
  510. break;
  511. case 3:
  512. shipLength = 3;
  513. break;
  514. case 4:
  515. shipLength = 2;
  516. }
  517.  
  518. //PICK H OR V.
  519. pick = Math.random();
  520. if(pick >= 0.5){
  521. console.log("Ori pick: " + pick);
  522. directions = 'v';
  523. }
  524. else if(pick < 0.5){
  525. console.log("Ori pick: " + pick);
  526. directions = 'h';
  527. }
  528.  
  529.  
  530.  
  531. //do{
  532. if(directions = 'h'){
  533. xP = Math.floor(Math.random()*(10-shipLength));
  534. yP = Math.floor(Math.random()*10);
  535.  
  536. }
  537. else{
  538. xP = Math.floor(Math.random()*10);
  539. yP = Math.floor(Math.random()*(10-shipLength));
  540.  
  541. }
  542.  
  543. conflictions = false;
  544.  
  545. for(let j = 0; j < shipLength; j++) {
  546.  
  547. if(directions == 'v') {
  548. // Check down
  549. if(xP + j <= 9){
  550. if(tempBoard[xP+j][yP].value == 's') {
  551. conflictions = true;
  552. }
  553. }
  554. else{
  555. conflictions = true;
  556. }
  557. }
  558. else if (directions == 'h') {
  559. if(yP + j <= 9){
  560. if(tempBoard[xP][yP+j].value == 's'){
  561. conflictions = true;
  562. }
  563. }
  564. else{
  565. conflictions =true;
  566. }
  567. }
  568. }
  569. }while(conflictions == true);
  570.  
  571. for(let j = 0; j < shipLength; j++){
  572. if(directions = 'v'){
  573. tempBoard[xP + j][yP].value = 's';
  574. }
  575. else{
  576. tempBoard[xP][yP+j].value = 's';
  577. }
  578.  
  579. }
  580.  
  581.  
  582. ships.push({length: shipLength, direction: 'h', damage: 0, destroyed: false, x: xP, y: yP});
  583. }
  584.  
  585.  
  586.  
  587.  
  588.  
  589. /*
  590.  
  591.  
  592.  
  593. let shipsArray = [];
  594. let ships = [
  595. {length: 5, direction: 'h', damage: 0, destroyed: false, x: 0, y: 0},
  596. {length: 4, direction: 'h', damage: 0, destroyed: false, x: 2, y: 0},
  597. {length: 3, direction: 'h', damage: 0, destroyed: false, x: 4, y: 0},
  598. {length: 3, direction: 'h', damage: 0, destroyed: false, x: 6, y: 0},
  599. {length: 2, direction: 'h', damage: 0, destroyed: false, x: 8, y: 0}
  600. ];*/
  601.  
  602. /*
  603. shipsArray.push(ships);
  604.  
  605. ships = [
  606. {length: 5, direction: 'v', damage: 0, destroyed: false, x: 0, y: 0},
  607. {length: 4, direction: 'v', damage: 0, destroyed: false, x: 0, y: 2},
  608. {length: 3, direction: 'v', damage: 0, destroyed: false, x: 0, y: 4},
  609. {length: 3, direction: 'v', damage: 0, destroyed: false, x: 0, y: 6},
  610. {length: 2, direction: 'v', damage: 0, destroyed: false, x: 0, y: 8}
  611. ];*/
  612.  
  613.  
  614.  
  615.  
  616.  
  617. return ships;
  618.  
  619.  
  620.  
  621. }
  622.  
  623.  
  624. /*-----------------------AI Chat Method------------------------*/
  625.  
  626. function aiChat(board, skillLevel, firstGame){
  627. //Boolean if the AI has made its first move.
  628.  
  629. //Also determine what stage of the game we are at for the AI chat feature.
  630. let movesMade = 0;
  631.  
  632. for(let i=0; i<10; i++){
  633. for(let j=0; j<10; j++){
  634. if(board[i][j].value == 'm' || board[i][j].value == 'h' || board[i][j].value == 'd') {
  635. movesMade++;
  636. }
  637. }
  638. }
  639.  
  640. //Code for AI commenting on the difficulty.
  641. //This code outputs to the chat when the AI makes its first move.
  642. if(movesMade == 0){
  643. let toReturn = '';
  644.  
  645. //Potentially remove this message. - or place it somewhere so it only posts when the player chooses the AI mode.
  646. if(firstGame == true){
  647. toReturn += "Hello! I am the Battleships AI! ";
  648. }
  649.  
  650. else {
  651. toReturn += "Another game! Lets go! ";
  652. }
  653.  
  654. //Comments on the chosen difficulty.
  655. if(skillLevel == 1){
  656. toReturn += "Hardest difficulty eh? Admirable, I'm going to be very hard to beat! \
  657. I may have an advantage over you as well...\
  658. All abilities activated!";
  659. }
  660. else if(skillLevel == 0){
  661. toReturn += "Wow, easiest difficulty? Really? I thought you were better than this! \
  662. My moves will be completely random!";
  663. }
  664. else if(skillLevel < 1 && skillLevel >= 0.7){
  665. toReturn += "Level " + skillLevel*10 + " is a respectable difficulty! Well done! \
  666. Hunting Ability Activated! Advanced Search Mode Activated! Advanced Hunt Mode Activated(With potential to not work)!";
  667. }
  668. else if(skillLevel < 0.7 && skillLevel >= 0.4){
  669. toReturn += "Hmmm, you have chosen level " + skillLevel*10 + "? You can do better than this! \
  670. Hunting Ability Activated! Advanced Search Mode Activated(With potential to not work)!";
  671. }
  672. else if(skillLevel < 0.4 && skillLevel >= 0){
  673. toReturn += "You a beginner? Because " + skillLevel*10 + " is not a hard level! \
  674. Hunting Ability Activated(With potential to not work!)";
  675. }
  676.  
  677. return toReturn;
  678. }
  679. else{
  680. let toReturn = '';
  681.  
  682. //Code for AI commenting on the result of the game.
  683. /*
  684. //Code for the AI commenting on winning.
  685. if(checkWin(???)){
  686. toReturn += "Yes I win!! In your face ;) ";
  687.  
  688. if(skillLevel == 1){
  689. toReturn += "It is the hardest difficulty, so no shame for you. ";
  690. }
  691. else if(skillLevel == 0){
  692. toReturn += "I beat you on the easiest difficulty as well... I wouldn't tell your friends about this... ";
  693. }
  694.  
  695. toReturn += "Want to play again?";
  696. return toReturn;
  697. }
  698. //Code for the AI commenting on losing.
  699. else if(checkWin(??)){
  700. toReturn += "You win! Well done, but I'll get you next time... ";
  701.  
  702. if(skillLevel != 1){
  703. toReturn += "Try upping the difficulty if you are confident ;) ";
  704. }
  705.  
  706. toReturn += "Want to play again? ";
  707. return toReturn;
  708. }
  709. */
  710.  
  711. }
  712. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement