Search Unity

NullReferenceException in a total weird Space (Checkers AI)

Discussion in 'Scripting' started by keimen, Sep 18, 2017.

  1. keimen

    keimen

    Joined:
    Nov 24, 2016
    Posts:
    5
    Good Evening, i´m currently working on a Checkers Board Game (Specifically on the AI)

    NullReferenceException: Object reference not set to an instance of an object
    AI2.GetMoves () (at Assets/NewAI/AI2.cs:224)
    AI2.minimax (Int32 depth, Int32 turn) (at Assets/NewAI/AI2.cs:123)
    AI2.minimax (Int32 depth, Int32 turn) (at Assets/NewAI/AI2.cs:142)
    AI2.minimax (Int32 depth, Int32 turn) (at Assets/NewAI/AI2.cs:158)
    AI2.minimax (Int32 depth, Int32 turn) (at Assets/NewAI/AI2.cs:142)
    AI2.minimax (Int32 depth, Int32 turn) (at Assets/NewAI/AI2.cs:158)
    AI2.minimax (Int32 depth, Int32 turn) (at Assets/NewAI/AI2.cs:142)
    AI2.minimax (Int32 depth, Int32 turn) (at Assets/NewAI/AI2.cs:158)
    AI2.minimax (Int32 depth, Int32 turn) (at Assets/NewAI/AI2.cs:142)
    AI2.callMiniMax (Int32 depth, Int32 turn) (at Assets/NewAI/AI2.cs:112)
    AI2.AIMove () (at Assets/NewAI/AI2.cs:40)


    So this is the Full Error, it runs through without Problems 7 times but suddenly there is an error ?
    Attached the full code at the bottom if anyone can help it would be SOOOO much appreciated (every tip counts)

    Thanks & Greetz
    Kai

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Node
    6. {
    7.     public int x;
    8.     public int y;
    9.     public int player = 0; // 1 = white 2 = whiteQueen 3= black 4 = blackQueen
    10.     public bool mustTake = false;
    11. }
    12. public class MoveScore
    13. {
    14.     public int score;
    15.     public Node point;
    16.  
    17.     public MoveScore(int score , Node point)
    18.     {
    19.         this.score = score;
    20.         this.point = point;
    21.     }
    22. }
    23.  
    24. public class AI2 : MonoBehaviour {
    25.     Node[,] grid = new Node[8,8];
    26.     public List<MoveScore> rootsChildrenScore;
    27.     int moves;
    28.  
    29.  
    30.     public void AIMove()
    31.     {
    32.         Debug.Log ("AIMove");
    33.         for (int x = 0; x < 8; x++) {
    34.             for (int y = 0; y < 8; y++) {
    35.                 grid [x, y] = new Node ();
    36.             }
    37.         }
    38.         GetField ();
    39.  
    40.         callMiniMax (0,1);
    41.         Node best = returnBestMove ();
    42.  
    43.         Debug.Log ("---" + best.x.ToString () + " " + best.y.ToString () + "---");
    44.     }
    45.  
    46.     void GetField()
    47.     {
    48.         Debug.Log ("GetField");
    49.  
    50.         for (int i = 0; i < gameObject.GetComponent<BoardScript>().Fields.Length; i++) {
    51.             grid [gameObject.GetComponent<BoardScript> ().Fields [i].GetComponent<BoardFieldScript> ().x, gameObject.GetComponent<BoardScript> ().Fields [i].GetComponent<BoardFieldScript> ().y].x = gameObject.GetComponent<BoardScript> ().Fields [i].GetComponent<BoardFieldScript> ().x;
    52.             grid [gameObject.GetComponent<BoardScript> ().Fields [i].GetComponent<BoardFieldScript> ().x, gameObject.GetComponent<BoardScript> ().Fields [i].GetComponent<BoardFieldScript> ().y].y = gameObject.GetComponent<BoardScript> ().Fields [i].GetComponent<BoardFieldScript> ().y;
    53.             grid [gameObject.GetComponent<BoardScript> ().Fields [i].GetComponent<BoardFieldScript> ().x, gameObject.GetComponent<BoardScript> ().Fields [i].GetComponent<BoardFieldScript> ().y].player = 0;
    54.             if (gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().occupied == true && gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().white == true) {
    55.                 if (gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().queen == false) {
    56.                     grid [gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().x, gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().y].player = 1;
    57.                 } else if (gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().queen == true) {
    58.                     grid [gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().x, gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().y].player = 2;
    59.                 }
    60.             } else if (gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().occupied == true && gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().white == false) {
    61.                 if (gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().queen == false) {
    62.                     grid [gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().x, gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().y].player = 3;
    63.                 } else if (gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().queen == true) {
    64.                     grid [gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().x, gameObject.GetComponent<BoardScript>().Fields [i].GetComponent<BoardFieldScript> ().y].player = 4;
    65.                 }
    66.             }
    67.         }
    68.     }
    69.  
    70.  
    71.  
    72.     public Node returnBestMove()
    73.     {
    74.         Debug.Log ("RETURN BEST");
    75.  
    76.         int MAX = -1000;
    77.         int best = -1;
    78.  
    79.  
    80.         for (int i = 0; i < rootsChildrenScore.Count; i++) {
    81.             if(MAX < rootsChildrenScore[i].score && isValidMove(rootsChildrenScore[i].point.x,rootsChildrenScore[i].point.y))
    82.                 {
    83.                 MAX = rootsChildrenScore [i].score;
    84.                 best = i;
    85.                 }
    86.         }
    87.  
    88.         if (best > -1) {
    89.             return rootsChildrenScore [best].point;
    90.         }
    91.         Node blank = new Node ();
    92.         blank.x = 0;
    93.         blank.y = 0;
    94.         Debug.Log ("Return What");
    95.         return blank;
    96.     }
    97.  
    98.     public bool isValidMove(int x , int y){
    99.  
    100.         if (grid [x, y].player == 0) {
    101.             return true;
    102.         } else
    103.             return false;
    104.        
    105.     }
    106.  
    107.     void callMiniMax(int depth,int turn)
    108.     {
    109.         Debug.Log ("callMiniMax");
    110.  
    111.         rootsChildrenScore = new List<MoveScore> ();
    112.         minimax (depth, turn);
    113.     }
    114.  
    115.     public int minimax(int depth,int turn)
    116.     {
    117.         Debug.Log ("MiniMax");
    118.  
    119.         if (hasWhiteWon ())
    120.             return +1;
    121.         if (hasBlackWon ())
    122.             return -1;
    123.         List<Node> pointsAvailable = GetMoves ();
    124.  
    125.         if (pointsAvailable.Capacity == 0) {
    126.             Debug.Log ("WHAT");
    127.             return 0;
    128.         }
    129.  
    130.         List<int> scores = new List<int> ();
    131.         for (int i = 0; i < pointsAvailable.Count; i++) {
    132.             Node point = pointsAvailable [i];
    133.             Debug.Log (i.ToString () + "TURN " + turn.ToString());
    134.  
    135.             if (turn == 1) {
    136.                 Debug.Log ("Turn 1");
    137.                 Node x = new Node ();
    138.                 x.x = point.x;
    139.                 x.y = point.y;
    140.                 x.player = 2;
    141.                 grid [point.x, point.y] = x;
    142.                 int currentScore = minimax (depth + 1, 2);
    143.                 scores.Add (currentScore);
    144.                 if (depth == 0) {
    145.                     Debug.Log ("Depth 0");
    146.                     MoveScore m = new MoveScore (currentScore, point);
    147.                     m.point = point;
    148.                     m.score = currentScore;
    149.                     rootsChildrenScore.Add (m);
    150.                 }
    151.             } else if (turn == 2) {
    152.                 Debug.Log("Turn 2");
    153.                 Node o = new Node ();
    154.                 o.x = point.x;
    155.                 o.y = point.y;
    156.                 o.player = 1;
    157.                 grid [point.x, point.y] = o;
    158.                 int currentScore = minimax (depth + 1, 1);
    159.                 scores.Add (currentScore);
    160.                 turn = 1;
    161.             }
    162.             grid [point.x, point.y] = null;
    163.         }
    164.         Debug.Log ("RETURN");
    165.         return turn == 1 ? returnMax (scores) : returnMin (scores);
    166.     }
    167.  
    168.     public int returnMin(List<int> list){
    169.         Debug.Log ("ReturnMin");
    170.         int min = 100000;
    171.         int index = -1;
    172.         for (int i = 0; i < list.Count; i++) {
    173.             if (list [i] < min) {
    174.                 min = list [i];
    175.                 index = i;
    176.             }
    177.         }
    178.         return list [index];
    179.     }
    180.  
    181.     public int returnMax(List<int> list){
    182.         Debug.Log ("ReturnMax");
    183.         int max = -100000;
    184.         int index = -1;
    185.         for (int i = 0; i < list.Count; i++) {
    186.             Debug.Log (i.ToString());
    187.             if (list [i] > max) {
    188.                
    189.                 max = list [i];
    190.                 index = i;
    191.                 Debug.Log ("MAX");
    192.             }
    193.         }
    194.         return list [index];
    195.     }
    196.  
    197.     List<Node> GetTakes()
    198.     {
    199.         List<Node> result = new List<Node> ();
    200.  
    201.  
    202.         return result;
    203.     }
    204.  
    205.     List<Node> GetMoves()
    206.     {
    207.         Debug.Log ("GetMoves");
    208.         List<Node> result = new List<Node> ();
    209.         int count = 0;
    210.  
    211.         for (int x = 0; x < 8; x++) {
    212.             for (int y = 0; y < 8; y++) {
    213.                 Debug.Log (x.ToString () + y.ToString ());
    214.  
    215.                 if (grid [x, y].player != 0) {
    216.                     if (grid [x, y].player == 1) {
    217.                         // whitepawn
    218.                         if (x > 0 && y > 0 && grid [x - 1, y - 1].player == 0) {
    219.                             result.Add (grid [x - 1, y - 1]);
    220.                             result [count].x = grid [x - 1, y - 1].x;
    221.                             result [count].y = grid [x - 1, y - 1].y;
    222.                             count++;
    223.                         }
    224.                         if (x < 7 && y > 0 && grid [x + 1, y - 1].player == 0) {
    225.  
    226.                             result.Add (grid [x + 1, y - 1]);
    227.                             result [count].x = grid [x + 1, y - 1].x;
    228.                             result [count].y = grid [x + 1, y - 1].y;
    229.                             count++;
    230.                         }
    231.                     } else if (grid [x, y].player == 3) {
    232.                         if (x > 0 && y < 7 && grid [x - 1, y + 1].player == 0) {
    233.                             result.Add (grid [x - 1, y + 1]);
    234.                             result [count].x = grid [x - 1, y + 1].x;
    235.                             result [count].y = grid [x - 1, y + 1].y;
    236.                             count++;
    237.                         }
    238.                         if (x < 7 && y < 7 && grid [x + 1, y + 1].player == 0) {
    239.                             result.Add (grid [x + 1, y + 1]);
    240.                             result [count].x = grid [x + 1, y + 1].x;
    241.                             result [count].y = grid [x + 1, y + 1].y;
    242.                             count++;
    243.                         }
    244.                     }
    245.                 }
    246.             }
    247.         }
    248.  
    249.         Debug.Log ("RETURN RESULT WITH THE COUNT OF " + count.ToString ());
    250.  
    251.         return result;
    252.     }
    253.  
    254.     public bool isValidMove(Node selected,int x,int y){
    255.         if (selected.player == 1) {
    256.             if (grid [x - 1, y - 1].player == 0 || grid [x + 1, y - 1].player == 0)
    257.                 return true;
    258.             else
    259.                 return false;
    260.         } else if (selected.player == 2) {
    261.             return true;
    262.  
    263.         } else if (selected.player == 3) {
    264.             if (grid [x - 1, y + 1].player == 0 || grid [x + 1, y + 1].player == 0)
    265.                 return true;
    266.             else
    267.                 return false;
    268.  
    269.         } else if (selected.player == 4) {
    270.             return true;
    271.  
    272.         } else
    273.             return false;
    274.     }
    275.  
    276.  
    277.     bool hasBlackWon()
    278.     {
    279.         Debug.Log ("HasBlackWon");
    280.  
    281.         for (int y = 0; y < 8; y++) {
    282.             for (int x = 0; x < 8; x++) {
    283.                 if (grid [x, y].player == 1 || grid [x, y].player == 2 ) {
    284.                     Debug.Log ("No");
    285.  
    286.                     return false;
    287.  
    288.                 }
    289.             }
    290.         }
    291.         return true;
    292.     }
    293.  
    294.     bool hasWhiteWon()
    295.     {
    296.         Debug.Log ("hasWhiteWon");
    297.  
    298.         bool won = true;
    299.         for (int y = 0; y < 8; y++) {
    300.             for (int x = 0; x < 8; x++) {
    301.                 if (grid [x, y].player == 3 || grid [x, y].player == 4 ) {
    302.                     Debug.Log ("No");
    303.  
    304.                     return false;
    305.  
    306.                 }
    307.             }
    308.         }
    309.         return true;
    310.     }
    311. }
     
  2. fire7side

    fire7side

    Joined:
    Oct 15, 2012
    Posts:
    1,819
    It's a little hard to tell, but I noticed you used two if's in a row, which generally is a bad idea unless you very specifically mean to do it because one if can change the results of the next one. It's always best to use an if/else if/ or else.
     
  3. Xepherys

    Xepherys

    Joined:
    Sep 9, 2012
    Posts:
    204
    Does ever grid position on the board contain a .player object? Looking at line 224, a null ref would only really be triggered if the value of grid [x + 1, y - 1].player is null.

    Is it always the same line? If so, set a break point on it and run the game. See what happens when it gets to the break. What is the value of that variable?
     
  4. keimen

    keimen

    Joined:
    Nov 24, 2016
    Posts:
    5
    yes ever object contains a .player object the weird thing is it runs 6-8 times (depending on the positions its calculating with) but than gives the error

    i´ll try the break and report in a moment thanks
     
    Xepherys likes this.
  5. keimen

    keimen

    Joined:
    Nov 24, 2016
    Posts:
    5
    its specific here for later would rly like to avoid using && or else here