Professional Documents
Culture Documents
import
import
import
import
import
import
import
java.io.BufferedReader;
java.io.BufferedWriter;
java.io.File;
java.io.FileReader;
java.io.FileWriter;
java.io.IOException;
java.util.Arrays;
java.util.LinkedList;
/**
*
* @author Ajay
*/
public class mancala {
public static void main(String[] args) throws IOException {
File f = new File("next_state.txt");
if (!f.exists()) {
f.createNewFile();
}
try (BufferedWriter writer = new BufferedWriter(new
FileWriter(f))) {
//Clears out existing file contents
writer.write("");
if (args.length > 1) {
String inputFile = args[1] != null ? args[1] : "";
if(!inputFile.contains(".txt"))
{
inputFile = inputFile.concat(".txt");
}
parseInputAndProcess(inputFile, writer);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
static ProblemState prbState;
static void parseInputAndProcess(String fileName, BufferedWriter
writer) throws Exception {
try {
BufferedReader reader = new BufferedReader(new
FileReader(fileName));
int task = Integer.parseInt(reader.readLine());
int player = Integer.parseInt(reader.readLine());
int cutOffDepth = Integer.parseInt(reader.readLine());
String player2StateRaw = reader.readLine().trim();
String[] temp = player2StateRaw.split(" ");
int[] player2State = new int[temp.length];
for (int i = 0; i < temp.length; i++) {
player2State[i] = Integer.parseInt(temp[i]);
}
class ProblemState {
int taskType;
int player;
int cutOffDepth;
MancalaState state;
public ProblemState(int taskType, int player, int cutOffDepth,
MancalaState state) {
this.taskType = taskType;
this.player = player;
this.cutOffDepth = cutOffDepth;
this.state = state;
}
}
class Action {
int stones;
int pit;
public Action(int stones, int pit) {
this.stones = stones;
this.pit = pit;
}
}
class MancalaState {
String nodeName;
String nodeData;
int[] player1State;
int[] player2State;
int numOfStonesInPlayer1Mancala;
int numOfStonesInPlayer2Mancala;
int player;
int rootPlayer;
int numOfPits;
boolean hasToPlayAgain = false;
int depth;
boolean playerSwitched = false;
// Used to find next state in Minimax and Alpha Beta
MancalaState child = null;
int eval = Integer.MAX_VALUE;
boolean isGameOver = false;
boolean isLeafNode = false;
// Alpha Beta related properties
int alpha = Integer.MIN_VALUE;
int beta = Integer.MAX_VALUE;
public MancalaState(MancalaState state) {
this.player1State = state.player1State.clone();
this.player2State = state.player2State.clone();
this.numOfStonesInPlayer1Mancala =
state.numOfStonesInPlayer1Mancala;
this.numOfStonesInPlayer2Mancala =
state.numOfStonesInPlayer2Mancala;
this.player = state.player;
this.numOfPits = state.player1State.length;
this.nodeName = state.nodeName;
this.rootPlayer = state.rootPlayer;
this.eval = state.eval;
this.alpha = state.alpha;
this.beta = state.beta;
}
public MancalaState(MancalaState state, int alpha, int beta) {
this(state);
this.alpha = alpha;
this.beta = beta;
}
public MancalaState(int[] player1State, int[] player2State, int
numOfStonesInPlayer1Mancala, int numOfStonesInPlayer2Mancala, int player)
{
this.player1State = player1State.clone();
this.player2State = player2State.clone();
this.numOfStonesInPlayer1Mancala = numOfStonesInPlayer1Mancala;
this.numOfStonesInPlayer2Mancala = numOfStonesInPlayer2Mancala;
this.player = player;
this.rootPlayer = player;
this.numOfPits = player1State.length;
this.hasToPlayAgain = false;
firstInit();
}
public int evaluation() {
return this.rootPlayer == 1 ? this.numOfStonesInPlayer1Mancala this.numOfStonesInPlayer2Mancala
: this.numOfStonesInPlayer2Mancala this.numOfStonesInPlayer1Mancala;
}
public void calculateEval() {
this.eval = this.evaluation();
}
private void firstInit(){
this.depth = 0;
this.hasToPlayAgain = true;
this.nodeName = "root";
this.eval = Integer.MIN_VALUE;
}
private int numOfStonesInPlayer1Pit() {
int retVal = 0;
for (int i : this.player1State) {
retVal += i;
}
return retVal;
}
private int numOfStonesInPlayer2Pit() {
int retVal = 0;
for (int i : this.player2State) {
retVal += i;
}
return retVal;
}
public LinkedList<Action> GetActions() {
LinkedList<Action> actions = new LinkedList<>();
if (this.player == 1) {
for (int i = 0; i < player1State.length; i++) {
if (player1State[i] != 0) {
actions.add(new Action(player1State[i], i));
}
}
} else {
for (int i = 0; i < player2State.length; i++) {
if (player2State[i] != 0) {
actions.add(new Action(player2State[i], i));
}
}
}
return actions;
}
public MancalaState ExcuteAction(Action action, int depth) {
MancalaState state = new MancalaState(this);
state.depth = depth;
try {
int last = Integer.MAX_VALUE;
state.eval = state.depth % 2 == 0 ? Integer.MIN_VALUE :
Integer.MAX_VALUE;
if (state.player == 1) {
state.nodeName = "B" + (action.pit + 2);
// Updating all the pits and mancalas if stones complete
rotations
state.player1State[action.pit] = 0;
int numOfRevolutionRequired = action.stones /
((state.numOfPits * 2) + 1);
state.updateStonesInMancala(numOfRevolutionRequired);
action.stones -= numOfRevolutionRequired *
((state.numOfPits * 2) + 1);
if (state.player1State[last] == 1) {
int temp = state.player2State[last] + 1;
state.numOfStonesInPlayer1Mancala += temp;
state.player2State[last] = 0;
state.player1State[last] = 0;
}
}
} else {
state.nodeName = "A" + (action.pit + 2);
// Updating all the pits and mancalas if stones complete
rotations
state.player2State[action.pit] = 0;
int numOfRevolutionRequired = action.stones /
((state.numOfPits * 2) + 1);
state.updateStonesInMancala(numOfRevolutionRequired);
action.stones -= numOfRevolutionRequired *
((state.numOfPits * 2) + 1);
// After revolution if no stones are left then last stone
was put in empt pit. Then empty that one and opposite pit
if(numOfRevolutionRequired == 1 && action.stones == 0){
int temp = state.player1State[action.pit] + 1;
state.numOfStonesInPlayer2Mancala += temp;
state.player1State[action.pit] = 0;
state.player2State[action.pit] = 0;
}
// Fill pits to the left
if (action.stones != 0) {
for (int i = action.pit - 1; i >= 0 && action.stones
!= 0; i--) {
state.player2State[i] += 1;
--action.stones;
if (action.stones == 0) {
last = i;
}
}
}
// Fill Player's mancala
if (action.stones != 0) {
state.numOfStonesInPlayer2Mancala += 1;
--action.stones;
if (action.stones == 0) {
state.hasToPlayAgain = true;
}
}
// Fill Opposition's pits
if (action.stones != 0) {
}
class MiniMax {
static BufferedWriter writer;
private static void init() throws IOException {
try {
File f = new File("traverse_log.txt");
if (!f.exists()) {
f.createNewFile();
}
writer = new BufferedWriter(new FileWriter(f));
writer.write("Node,Depth,Value");
writer.append(System.getProperty("line.separator"));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static MancalaState processMinimax(MancalaState state) throws
IOException {
if (writer == null) {
init();
}
state.updateNodedata();
writer.append(state.nodeData);
MancalaState temp = MIN_VALUE(state);
MancalaState optimalState = null;
boolean found = false;
while(!found){
optimalState = temp.child;
if(optimalState != null && optimalState.child != null){
temp = optimalState;
optimalState = optimalState.child;
}
else found = true;
}
writer.close();
return optimalState == null ? state : optimalState;
}
private static MancalaState MAX_VALUE(MancalaState state) throws
IOException {
if (state.hasToPlayAgain) {
for (Action a : state.GetActions()) {
MancalaState temp = state.ExcuteAction(a, state.depth);
writer.append(temp.nodeData);
MancalaState t = MAX_VALUE(temp);
printEvaluatedValForGameOver(t, temp.nodeData);
state.eval = min(state.eval, t.eval);
if (state.playerSwitched) {
state.updateNodedata(state.depth - 1);
} else {
state.updateNodedata();
}
writer.append(state.nodeData);
}
return state;
}
if (state.depth == mancala.prbState.cutOffDepth) {
return state;
}
if (!state.hasToPlayAgain) {
MancalaState t = new MancalaState(state);
t.depth = state.depth + 1;
if (state.player == 1) {
t.player = 2;
} else {
t.player = 1;
}
t.playerSwitched = true;
t.hasToPlayAgain = true;
MancalaState temp = MIN_VALUE(t);
state.eval = max(state.eval, temp.eval);
return state;
}
return state;
}
private static MancalaState MIN_VALUE(MancalaState state) throws
IOException {
if (state.hasToPlayAgain) {
for (Action a : state.GetActions()) {
MancalaState temp = state.ExcuteAction(a, state.depth ==
0 ? 1 : state.depth);
writer.append(temp.nodeData);
MancalaState t = MIN_VALUE(temp);
printEvaluatedValForGameOver(t, temp.nodeData);
max(state, t);
if (state.playerSwitched) {
state.updateNodedata(state.depth - 1);
} else {
state.updateNodedata();
}
writer.append(state.nodeData);
}
return state;
}
if (state.depth == mancala.prbState.cutOffDepth) {
return state;
}
if (!state.hasToPlayAgain) {
MancalaState t = new MancalaState(state);
t.depth = state.depth + 1;
if (state.player == 1) {
t.player = 2;
} else {
t.player = 1;
}
t.playerSwitched = true;
t.hasToPlayAgain = true;
MancalaState temp = MAX_VALUE(t);
state.eval = min(state.eval, temp.eval);
return state;
}
return state;
}
private static int min(int s1, int s2) {
return s1 < s2 ? s1 : s2;
}
private static int max(int s1, int s2) {
if (s1 == Integer.MAX_VALUE) {
return s2;
} else if (s2 == Integer.MAX_VALUE) {
return s1;
} else {
return s1 > s2 ? s1 : s2;
}
}
private static void max(MancalaState s1, MancalaState s2) {
if (s1.eval == Integer.MAX_VALUE) {
s1.eval = s2.eval;
s1.child = s2;
} else {
if(s2.eval > s1.eval)
{
s1.eval = s2.eval;
s1.child = s2;
}
}
}
private static void printEvaluatedValForGameOver(MancalaState state,
String prevData) throws IOException
{
if(state.isGameOver){
state.calculateEval();
if (state.playerSwitched) {
state.updateNodedata(state.depth - 1);
} else {
state.updateNodedata();
}
if(!prevData.endsWith(state.nodeData)){
writer.append(state.nodeData);
}
}
}
}
class AlphaBeta {
static BufferedWriter writer;
private static void init() throws IOException {
try {
File f = new File("traverse_log.txt");
if (!f.exists()) {
f.createNewFile();
}
writer = new BufferedWriter(new FileWriter(f));
writer.write("Node,Depth,Value,Alpha,Beta");
writer.append(System.getProperty("line.separator"));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static MancalaState processAlphaBeta(MancalaState state)
throws IOException
{
if (writer == null) {
init();
}
state.updateNodedata();
writer.append(state.nodeData);
MancalaState temp = Min_Value(state);
MancalaState optimalState = null;
boolean found = false;
while(!found){
optimalState = temp.child;
if(optimalState != null && optimalState.child != null){
temp = optimalState;
optimalState = optimalState.child;
}
else found = true;
}
writer.close();
return optimalState == null ? state : optimalState;
}
private static MancalaState Max_Value(MancalaState state) throws
IOException
{
if (state.hasToPlayAgain) {
for (Action a : state.GetActions()) {
MancalaState temp = state.ExcuteAction(a, state.depth);
writer.append(temp.nodeData);
MancalaState t = Max_Value(temp);
printEvaluatedValForGameOver(t, temp.nodeData);
// Player at max level having another chance. [Min node]
if(!state.playerSwitched && mancala.prbState.player !=
state.player && !state.isLeafNode){
state.eval = min(state.eval, t.eval);
if(state.alpha >= min(state.beta, t.eval)){
state.updateNodedata();
writer.append(state.nodeData);
state.beta = min(state.beta, t.eval);
}
else if(state.alpha < state.beta){
state.beta = min(state.beta, t.eval);
state.updateNodedata();
writer.append(state.nodeData);
}
}
// Player at min level [Max node]
else if(state.playerSwitched && !state.isLeafNode){
state.eval = min(state.eval, temp.eval);
if(state.alpha >= min(state.eval, t.eval)){
state.updateNodedata(state.depth-1);
writer.append(state.nodeData);
state.beta = min(state.beta, temp.eval);
}
else if(state.alpha < state.beta){
state.beta = min(state.beta, temp.eval);
state.updateNodedata(state.depth-1);
writer.append(state.nodeData);
}
}
if(state.alpha >= state.beta)
return state;
}
return state;
}
if (state.depth == mancala.prbState.cutOffDepth) {
return state;
}
if (!state.hasToPlayAgain) {
MancalaState t = new MancalaState(state);
t.depth = state.depth + 1;
if (state.player == 1) {
t.player = 2;
} else {
t.player = 1;
}
t.playerSwitched = true;
t.hasToPlayAgain = true;
MancalaState temp = Min_Value(t);
state.eval = temp.eval;
state.beta = temp.beta;
state.alpha = temp.alpha;
return state;
}
return state;
}
private static MancalaState Min_Value(MancalaState state) throws
IOException
{
if (state.hasToPlayAgain) {
for (Action a : state.GetActions()) {
MancalaState temp = state.ExcuteAction(a, state.depth ==
0 ? 1 : state.depth);
writer.append(temp.nodeData);
MancalaState t = Min_Value(temp);
printEvaluatedValForGameOver(t, temp.nodeData);
// Player at min level having another chance. [Max node]
if(!state.playerSwitched && mancala.prbState.player ==
state.player && !state.isLeafNode){
if(t.eval > state.eval){
state.eval = t.eval;
state.child = t;
state.updateNodedata();
}
if(state.beta <= max(state.alpha, t.eval)){
state.updateNodedata();
writer.append(state.nodeData);
max(state, t);
}
else if(state.alpha < state.beta){
max(state, t);
state.updateNodedata();
writer.append(state.nodeData);
}
}
// Player at max level [Min node]
else if(state.playerSwitched && !state.isLeafNode){
state.eval = max(state.eval, temp.eval);
if(state.beta <= max(state.alpha, t.eval)){
state.updateNodedata(state.depth-1);
writer.append(state.nodeData);
state.alpha = max(state.alpha, temp.eval);
}
else if(state.alpha < state.beta){
state.alpha = max(state.alpha, temp.eval);
state.updateNodedata(state.depth-1);
writer.append(state.nodeData);
}
}
if(state.beta <= state.alpha)
return state;
}
return state;
}
if (state.depth == mancala.prbState.cutOffDepth) {
return state;
}
if (!state.hasToPlayAgain) {
MancalaState t = new MancalaState(state);
t.depth = state.depth + 1;
if (state.player == 1) {
t.player = 2;
} else {
t.player = 1;
}
t.playerSwitched = true;
t.hasToPlayAgain = true;
MancalaState t1 = Max_Value(t);
state.eval = t1.eval;
state.beta = t1.beta;
state.alpha = t1.alpha;
return state;
}
return state;
}
private static int min(int s1, int s2) {
return s1 < s2 ? s1 : s2;
}
private static int max(int s1, int s2) {
if (s1 == Integer.MAX_VALUE) {
return s2;
} else if (s2 == Integer.MAX_VALUE) {
return s1;
} else {
return s1 > s2 ? s1 : s2;
}
}
private static void max(MancalaState s1, MancalaState s2) {
if(s2.eval > s1.alpha){
s1.alpha = s2.eval;
s1.child = s2;
}
}
private static void printEvaluatedValForGameOver(MancalaState state,
String prevData) throws IOException
{
if(state.isGameOver){
state.calculateEval();
if (state.playerSwitched) {
state.updateNodedata(state.depth - 1);
} else {
state.updateNodedata();
}
if(!prevData.equals(state.nodeData)){
writer.append(state.nodeData);
}
}
}
}