/RussianCheckers/RussianCheckers/AlphaBeta - Copy (6).cs
https://bitbucket.org/KuroKaze/russian-checkers · C# · 220 lines · 161 code · 34 blank · 25 comment · 47 complexity · 12e5db00cd5543148c3c9f238d20473a MD5 · raw file
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Graphics;
- using Microsoft.Xna.Framework.Input;
- namespace RussianCheckers
- {
- class AlphaBeta
- {
- long maxDepth = 0;
- long node = 1;
- long maxPrun = 0;
- long minPrun = 0;
- DateTime start;
- public AlphaBeta()
- {
- }
-
- public AlphaBeta(Environment env)
- {
- start = DateTime.Now;
- Tuple<int, int, int> value;
- if (!env.gameOver())
- {
- value = max(env, -100000, 100000, 1);
- env.doJump(value.Item2, value.Item3);
- env.possibleMoves[value.Item2].piece.newPosition(env.possibleMoves[value.Item2].markers[value.Item3].position);
- env.reset();
- Console.WriteLine("maxDepth = " + maxDepth + "\n" +
- "node = " + node + "\n" +
- "maxPruned = " + maxPrun + "\n" +
- "minPruned = " + minPrun + "\n" +
- "Value = " + value.Item1 + "\n" );
- }
- else
- env.winner = true;
- }
- Tuple<int, int, int> max(Environment env, int alpha, int beta, long depth)
- {
- if (depth > maxDepth)
- maxDepth = depth;
- node++;
- if (node % 100000 == 0)
- Console.WriteLine("depth = " + depth + "\n" +
- "node = " + node + "\n" +
- "maxPruned = " + maxPrun + "\n" +
- "minPruned = " + minPrun + "\n" +
- "Alpha beta= " + alpha + ", " + beta + "\n");
- List<Vector2> player = new List<Vector2>();
- List<Vector2> ai = new List<Vector2>();
- for (int i = 0; i < env.player.Count; i++)
- {
- player.Add(new Vector2(env.player[i].position.X, env.player[i].position.Y));
- ai.Add(new Vector2(env.ai[i].position.X, env.ai[i].position.Y));
- }
- bool playerTurn = env.playerTurn;
- if (env.playerTurn)
- Console.WriteLine("BADDDDDDD");
- long elapsedTicks = DateTime.Now.Ticks - start.Ticks;
- TimeSpan elapsedSpan = new TimeSpan(elapsedTicks);
- if (env.gameOver() || depth == 17 /*18 + Math.Pow(2.0, (double)env.turn)*/)
- return new Tuple<int, int, int>(env.utility(), 0, 0);
- //else if (elapsedSpan.TotalMinutes > 1)
- // return new Tuple<int, int, int>(-1000, 0, 0);
- Tuple<int, int, int> value = new Tuple<int, int, int>(-100000, 0, 0);
-
- for (int i = 0; i < env.possibleMoves.Count; i++)
- {
- for (int j = 0; j < env.possibleMoves[i].markers.Count && env.possibleMoves[i].markers[j].position != Vector2.Zero; j++)
- {
- if (env.possibleMoves[i].jumpSet[j].Count == 4)
- return new Tuple<int, int, int>(100000, i, j);
- else if (env.possibleMoves.Count == 1 && depth == 1)
- return new Tuple<int, int, int>(0, i, j);
- //else if (env.possibleMoves.Count == 1)
- // value = new Tuple<int, int, int>(env.utility(), i, 0);
- env.doJump(i, j);
- env.possibleMoves[i].piece.newPosition(env.possibleMoves[i].markers[j].position);
- env.reset();
- env.generateCanJump();
- env.generateJump();
- Tuple<int, int, int> minimum = min(env, alpha, beta, depth + 1);
- int score = Math.Max(value.Item1, minimum.Item1);
- if(value.Item1 != score)
- value = new Tuple<int, int, int>(score, i, j);
- for (int k = 0; k < player.Count; k++)
- {
- env.player[k].newPosition(player[k]);
- env.ai[k].newPosition(ai[k]);
- }
- env.reset();
- env.generateCanJump();
- env.generateJump();
- if (value.Item1 >= beta)
- {
- maxPrun++;
- return value;
- }
- alpha = Math.Max(alpha, value.Item1);
- }
- }
- return value;
- }
- Tuple<int, int, int> min(Environment env, int alpha, int beta, long depth)
- {
- if (depth > maxDepth)
- maxDepth = depth;
- node++;
- if (node % 100000 == 0)
- Console.WriteLine("depth = " + depth + "\n" +
- "node = " + node + "\n" +
- "maxPruned = " + maxPrun + "\n" +
- "minPruned = " + minPrun + "\n" +
- "Alpha beta= " + alpha + ", " + beta + "\n");
- List<Vector2> player = new List<Vector2>();
- List<Vector2> ai = new List<Vector2>();
-
- for (int i = 0; i < env.player.Count; i++)
- {
- player.Add(new Vector2(env.player[i].position.X, env.player[i].position.Y));
- ai.Add(new Vector2(env.ai[i].position.X, env.ai[i].position.Y));
- }
- bool playerTurn = env.playerTurn;
- if (!env.playerTurn)
- Console.WriteLine("BADDDDDDD");
-
- long elapsedTicks = DateTime.Now.Ticks - start.Ticks;
- TimeSpan elapsedSpan = new TimeSpan(elapsedTicks);
- if (env.gameOver() || depth == 17 /*18 + Math.Pow(2.0, (double)env.turn)*/)
- return new Tuple<int, int, int>(env.utility(), 0, 0);
- //else if (elapsedSpan.TotalMinutes > 1)
- // return new Tuple<int, int, int>(1000, 0, 0);
- Tuple<int, int, int> value = new Tuple<int, int, int>(100000, 0, 0);
- for (int i = 0; i < env.possibleMoves.Count; i++)
- {
- for (int j = 0; j < env.possibleMoves[i].markers.Count && env.possibleMoves[i].markers[j].position != Vector2.Zero; j++)
- {
- if (env.possibleMoves[i].jumpSet[j].Count == 4)
- return new Tuple<int, int, int>(-100000, i, j);
- else if (env.possibleMoves.Count == 1 && depth == 1)
- return new Tuple<int, int, int>(0, i, j);
- //else if (env.possibleMoves.Count == 1)
- // value = new Tuple<int, int, int>(env.utility(), i, 0);
- env.doJump(i, j);
- env.possibleMoves[i].piece.newPosition(env.possibleMoves[i].markers[j].position);
- env.reset();
- env.generateCanJump();
- env.generateJump();
- Tuple<int, int, int> maximum = max(env, alpha, beta, depth + 1);
- int score = Math.Min(value.Item1, maximum.Item1);
- if(value.Item1 != score)
- value = new Tuple<int, int, int>(score, i, j);
- for (int k = 0; k < player.Count; k++)
- {
- env.player[k].newPosition(player[k]);
- env.ai[k].newPosition(ai[k]);
- }
- env.reset();
- env.generateCanJump();
- env.generateJump();
- if (value.Item1 <= alpha)
- {
- minPrun++;
- return value;
- }
- beta = Math.Min(beta, value.Item1);
- }
- }
- return value;
- }
- // void alphabeta(node, depth, α, β, Player)
- // if depth = 0 or node is a terminal node
- // return the heuristic value of node
- // if Player = MaxPlayer
- // for each child of node
- // α := max(α, alphabeta(child, depth-1, α, β, not(Player) ))
- // if β ≤ α
- // break (* Beta cut-off *)
- // return α
- // else
- // for each child of node
- // β := min(β, alphabeta(child, depth-1, α, β, not(Player) ))
- // if β ≤ α
- // break (* Alpha cut-off *)
- // return β
- //(* Initial call *)
- //alphabeta(origin, depth, -infinity, +infinity, MaxPlayer)
- }
- }