private void CalculateTrajectory() { Trajectory.Clear(); Ray ray = new Ray(transform.position, ballRb.velocity.normalized); RaycastHit hit; bool endOfCourt = false; int sentinel = 1000; while (!endOfCourt && sentinel > 0) { if (Physics.Raycast(ray, out hit)) { if (hit.collider.gameObject.tag == "Wall") { Trajectory.Add(hit.point); var nextDir = Vector3.Reflect(ray.direction, hit.normal); ray = new Ray(hit.point, nextDir); } else if (hit.collider.gameObject.tag == "Goal") { Trajectory.Add(hit.point); endOfCourt = true; } else { Trajectory.Add(hit.point); // only other object is paddle, so we count as end endOfCourt = true; } } sentinel--; } }
private void Update() { trajectory.Clear(); Vector3 mousePosition = Input.mousePosition; mousePosition.z = 10; mousePosition = Camera.main.ScreenToWorldPoint(mousePosition); float power = Vector3.Distance(mousePosition, transform.position); Vector3 direction = (mousePosition - transform.position).normalized; if (Input.GetMouseButton(0)) { trajectory.Create(transform.position, direction * power * powerMultiplier); } if (Input.GetMouseButtonUp(0)) { Instantiate(ball, transform.position, Quaternion.identity).GetComponent <Rigidbody>().AddForce(direction * power * powerMultiplier); } }
//POGame poGame2; public override PlayerTask GetMove(POGame poGame) { var player = poGame.CurrentPlayer; // Implement a simple Mulligan Rule if (player.MulliganState == Mulligan.INPUT) { List <int> mulligan = new CustomScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); return(ChooseTask.Mulligan(player, mulligan)); } #if DEBUG Console.WriteLine($"root:{GetGameHashCode(poGame)}"); #endif PlayerTask bestAction = null; if (poGame.CurrentPlayer.Options().Count == 1) { bestAction = poGame.CurrentPlayer.Options()[0]; } else { stopwatchForThisTurn.Start(); long bestActionCode = 0; Trajectory trajectory = new Trajectory(); List <PlayerTask> taskToSimulate = new List <PlayerTask>(1); taskToSimulate.Add(null); POGame poGameRoot = poGame; Node root; long gameHashCodeRoot = GetGameHashCode(poGameRoot); if (!nodeHashMap.TryGetValue(gameHashCodeRoot, out root)) { root = new Node(); nodeHashMap.Add(gameHashCodeRoot, root); } Expand(root, poGameRoot); /*foreach (var child in root.edges) * { * Console.WriteLine(child.actionHashCode); * }*/ long think_time = (30 * 1000 - stopwatchForThisTurn.ElapsedMilliseconds) / Math.Max(3, 5 - movesInThisTurn); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); //for (int itr = 0; itr < 100; ++itr) while (stopwatch.ElapsedMilliseconds <= think_time) { Node node = root; poGame = poGameRoot.getCopy(); long gameHashCode = gameHashCodeRoot; long actionHashCodeNext = 0; bool simulateResult = true; int index = 0; trajectory.Clear(); // traverse do { index = Select(node); /*if (index >= node.edges.Count) * { * Console.WriteLine($"{index}, {node.edges.Count}, {node == root}"); * Debugger.Break(); * }*/ actionHashCodeNext = node.edges[index].actionHashCode; // Until the end of my own turn if (actionHashCodeNext == 0) { trajectory.Add((node, index)); break; } taskToSimulate[0] = null; foreach (PlayerTask task in poGame.CurrentPlayer.Options()) { if (GetActionHashCode(task) == actionHashCodeNext) { taskToSimulate[0] = task; break; } } if (taskToSimulate[0] == null) { // Hash key conflict return(poGame.CurrentPlayer.Options().First()); /*foreach (PlayerTask task in poGame.CurrentPlayer.Options()) * { * Console.WriteLine($"{task}, {GetActionHashCode(task)}"); * } * Console.WriteLine("---"); * foreach (var edge in node.edges) * { * Console.WriteLine($"{edge.task}, {edge.actionHashCode}"); * } * poGame2 = node.poGame; * Console.WriteLine(poGame2.Turn); * Console.WriteLine(gameHashCode); * Console.WriteLine("---"); * foreach (var minion in poGame.CurrentPlayer.BoardZone) * { * Console.WriteLine(minion.CantAttackHeroes); * } * var tasks = poGame.CurrentPlayer.Options(); * foreach (PlayerTask task in tasks) * { * Console.WriteLine($"{task}, {GetActionHashCode(task)}"); * } * Debugger.Break();*/ } poGame = poGame.Simulate(taskToSimulate)[taskToSimulate[0]]; long gameHashCodeNext = GetGameHashCode(poGame); if (gameHashCode == gameHashCodeNext) { // loop node.edges.RemoveAt(index); continue; } gameHashCode = gameHashCodeNext; trajectory.Add((node, index)); if (!nodeHashMap.TryGetValue(gameHashCode, out node)) { node = new Node(); //node.poGame = poGame; nodeHashMap.Add(gameHashCode, node); } } while (node.edges != null); if (simulateResult == false) { continue; } if (actionHashCodeNext != 0) { #if DEBUG Console.WriteLine($"expand:{gameHashCode}"); #endif Expand(node, poGame); float value = Simulate(node, poGame); Backup(trajectory, value); } else { float value; if (node.edges[index].visitCount == 0) { value = ScoreToValue(Score(poGame)); } else { value = node.edges[index].totalValue / node.edges[index].visitCount; } Backup(trajectory, value); } } stopwatch.Stop(); //Console.WriteLine($"{think_time}, {root.visitCount}, {root.visitCount * 1000 / stopwatch.ElapsedMilliseconds} nps"); // Choose the most visited node float best = Single.MinValue; foreach (Edge child in root.edges) { if (child.visitCount >= best) { best = child.visitCount; bestActionCode = child.actionHashCode; } } // Choose an action with a matching hash code foreach (PlayerTask task in poGameRoot.CurrentPlayer.Options()) { if (GetActionHashCode(task) == bestActionCode) { bestAction = task; break; } } } stopwatchForThisTurn.Stop(); ++movesInThisTurn; if (bestAction.PlayerTaskType == PlayerTaskType.END_TURN) { //Console.WriteLine(movesInThisTurn); stopwatchForThisTurn.Reset(); movesInThisTurn = 0; nodeHashMap.Clear(); } return(bestAction); }