Raven7 commited on
Commit
11faca4
·
verified ·
1 Parent(s): 7255ba2

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +264 -1
index.html CHANGED
@@ -478,9 +478,272 @@
478
  }
479
 
480
  makeStrategicMove() {
481
- this.makeRandomMove();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
482
  }
483
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
 
485
  const game = new GoGame();
486
  </script>
 
478
  }
479
 
480
  makeStrategicMove() {
481
+ const depth = this.difficulty === 'hard' ? 3 : 1;
482
+ let bestMove = this.findBestMove(depth);
483
+
484
+ if(bestMove) {
485
+ this.placeStone(bestMove[0], bestMove[1]);
486
+ } else {
487
+ this.pass();
488
+ }
489
+ }
490
+
491
+ findBestMove(depth) {
492
+ let bestScore = -Infinity;
493
+ let bestMove = null;
494
+
495
+ // 전체 보드를 평가
496
+ for(let i = 0; i < this.size; i++) {
497
+ for(let j = 0; j < this.size; j++) {
498
+ if(this.isValidMove(i, j)) {
499
+ // 임시로 돌을 놓아보고 평가
500
+ this.board[i][j] = 'white';
501
+ const score = this.minimax(depth - 1, false);
502
+ this.board[i][j] = null;
503
+
504
+ if(score > bestScore) {
505
+ bestScore = score;
506
+ bestMove = [i, j];
507
+ }
508
+ }
509
+ }
510
+ }
511
+
512
+ return bestMove;
513
+ }
514
+
515
+ minimax(depth, isMaximizing) {
516
+ if(depth === 0) {
517
+ return this.evaluateBoard();
518
+ }
519
+
520
+ if(isMaximizing) {
521
+ let maxScore = -Infinity;
522
+ for(let i = 0; i < this.size; i++) {
523
+ for(let j = 0; j < this.size; j++) {
524
+ if(this.isValidMove(i, j)) {
525
+ this.board[i][j] = 'white';
526
+ const score = this.minimax(depth - 1, false);
527
+ this.board[i][j] = null;
528
+ maxScore = Math.max(maxScore, score);
529
+ }
530
+ }
531
+ }
532
+ return maxScore;
533
+ } else {
534
+ let minScore = Infinity;
535
+ for(let i = 0; i < this.size; i++) {
536
+ for(let j = 0; j < this.size; j++) {
537
+ if(this.isValidMove(i, j)) {
538
+ this.board[i][j] = 'black';
539
+ const score = this.minimax(depth - 1, true);
540
+ this.board[i][j] = null;
541
+ minScore = Math.min(minScore, score);
542
+ }
543
+ }
544
+ }
545
+ return minScore;
546
+ }
547
+ }
548
+
549
+ evaluateBoard() {
550
+ return this.evaluateTerritory() +
551
+ this.evaluateInfluence() +
552
+ this.evaluateCaptureThreats() +
553
+ this.evaluateConnectivity();
554
+ }
555
+
556
+ evaluateTerritory() {
557
+ let score = 0;
558
+ const visited = new Set();
559
+
560
+ for(let i = 0; i < this.size; i++) {
561
+ for(let j = 0; j < this.size; j++) {
562
+ if(!visited.has(`${i},${j}`) && this.board[i][j] === null) {
563
+ const territory = this.floodFillTerritory(i, j, visited);
564
+ const owner = this.determineTerritorySide(territory);
565
+ if(owner === 'white') score += territory.size;
566
+ else if(owner === 'black') score -= territory.size;
567
+ }
568
+ }
569
+ }
570
+
571
+ return score;
572
+ }
573
+
574
+ floodFillTerritory(row, col, visited) {
575
+ const territory = new Set();
576
+ const stack = [[row, col]];
577
+ const borders = new Set();
578
+
579
+ while(stack.length > 0) {
580
+ const [r, c] = stack.pop();
581
+ const key = `${r},${c}`;
582
+
583
+ if(!visited.has(key)) {
584
+ visited.add(key);
585
+ if(this.board[r][c] === null) {
586
+ territory.add(key);
587
+
588
+ const neighbors = this.getNeighbors(r, c);
589
+ for(const [nr, nc] of neighbors) {
590
+ if(this.board[nr][nc] === null) {
591
+ stack.push([nr, nc]);
592
+ } else {
593
+ borders.add(`${nr},${nc}`);
594
+ }
595
+ }
596
+ }
597
+ }
598
+ }
599
+
600
+ territory.borders = borders;
601
+ return territory;
602
+ }
603
+
604
+ determineTerritorySide(territory) {
605
+ let blackCount = 0;
606
+ let whiteCount = 0;
607
+
608
+ for(const pos of territory.borders) {
609
+ const [row, col] = pos.split(',').map(Number);
610
+ if(this.board[row][col] === 'black') blackCount++;
611
+ else if(this.board[row][col] === 'white') whiteCount++;
612
+ }
613
+
614
+ if(blackCount > whiteCount) return 'black';
615
+ if(whiteCount > blackCount) return 'white';
616
+ return null;
617
+ }
618
+
619
+ evaluateInfluence() {
620
+ let score = 0;
621
+
622
+ for(let i = 0; i < this.size; i++) {
623
+ for(let j = 0; j < this.size; j++) {
624
+ if(this.board[i][j] === 'white') {
625
+ score += this.calculateInfluence(i, j, 3);
626
+ } else if(this.board[i][j] === 'black') {
627
+ score -= this.calculateInfluence(i, j, 3);
628
  }
629
  }
630
+ }
631
+
632
+ return score;
633
+ }
634
+
635
+ calculateInfluence(row, col, radius) {
636
+ let influence = 0;
637
+
638
+ for(let i = -radius; i <= radius; i++) {
639
+ for(let j = -radius; j <= radius; j++) {
640
+ const distance = Math.abs(i) + Math.abs(j);
641
+ if(distance <= radius) {
642
+ const newRow = row + i;
643
+ const newCol = col + j;
644
+
645
+ if(newRow >= 0 && newRow < this.size &&
646
+ newCol >= 0 && newCol < this.size) {
647
+ influence += (radius - distance + 1) / radius;
648
+ }
649
+ }
650
+ }
651
+ }
652
+
653
+ return influence;
654
+ }
655
+
656
+ evaluateCaptureThreats() {
657
+ let score = 0;
658
+
659
+ for(let i = 0; i < this.size; i++) {
660
+ for(let j = 0; j < this.size; j++) {
661
+ if(this.board[i][j]) {
662
+ const group = this.getGroup(i, j);
663
+ const liberties = this.countLiberties(group);
664
+
665
+ if(this.board[i][j] === 'white') {
666
+ score += liberties * 2;
667
+ if(liberties === 1) score -= 10;
668
+ } else {
669
+ score -= liberties * 2;
670
+ if(liberties === 1) score += 10;
671
+ }
672
+ }
673
+ }
674
+ }
675
+
676
+ return score;
677
+ }
678
+
679
+ countLiberties(group) {
680
+ const liberties = new Set();
681
+
682
+ for(const [row, col] of group) {
683
+ const neighbors = this.getNeighbors(row, col);
684
+ for(const [nRow, nCol] of neighbors) {
685
+ if(this.board[nRow][nCol] === null) {
686
+ liberties.add(`${nRow},${nCol}`);
687
+ }
688
+ }
689
+ }
690
+
691
+ return liberties.size;
692
+ }
693
+
694
+ evaluateConnectivity() {
695
+ let score = 0;
696
+
697
+ for(let i = 0; i < this.size; i++) {
698
+ for(let j = 0; j < this.size; j++) {
699
+ if(this.board[i][j] === 'white') {
700
+ score += this.evaluateStoneConnectivity(i, j);
701
+ } else if(this.board[i][j] === 'black') {
702
+ score -= this.evaluateStoneConnectivity(i, j);
703
+ }
704
+ }
705
+ }
706
+
707
+ return score;
708
+ }
709
+
710
+ evaluateStoneConnectivity(row, col) {
711
+ let connectivity = 0;
712
+ const neighbors = this.getNeighbors(row, col);
713
+ const diagonalNeighbors = this.getDiagonalNeighbors(row, col);
714
+
715
+ for(const [nRow, nCol] of neighbors) {
716
+ if(this.board[nRow][nCol] === this.board[row][col]) {
717
+ connectivity += 2;
718
+ }
719
+ }
720
+
721
+ for(const [nRow, nCol] of diagonalNeighbors) {
722
+ if(this.board[nRow][nCol] === this.board[row][col]) {
723
+ connectivity += 1;
724
+ }
725
+ }
726
+
727
+ return connectivity;
728
+ }
729
+
730
+ getDiagonalNeighbors(row, col) {
731
+ const neighbors = [];
732
+ const directions = [[-1,-1], [-1,1], [1,-1], [1,1]];
733
+
734
+ for(const [dRow, dCol] of directions) {
735
+ const newRow = row + dRow;
736
+ const newCol = col + dCol;
737
+
738
+ if(newRow >= 0 && newRow < this.size &&
739
+ newCol >= 0 && newCol < this.size) {
740
+ neighbors.push([newRow, newCol]);
741
+ }
742
+ }
743
+
744
+ return neighbors;
745
+ }
746
+ }
747
 
748
  const game = new GoGame();
749
  </script>