public State(State copy) { Hash = copy.Hash; NextState = copy.NextState; DepthToMate = copy.DepthToMate; PlayerTurn = copy.PlayerTurn; Pieces = new byte[] { copy.Pieces[0], copy.Pieces[1], copy.Pieces[2], copy.Pieces[3] }; PieceLocation = new byte[] { copy.PieceLocation[0], copy.PieceLocation[1], copy.PieceLocation[2], copy.PieceLocation[3] }; }
public List<State> CalculateBlack(List<State> stateSet) { // find only moves where black MUST move to a state in the stateSet var newStates = new List<State>(); var b = Board.Create(); foreach (var state in stateSet) { var originalHash = state.Hash; state.PlayerTurn = Board.COLOR_BLACK; state.Hash = CalcHash(state); SetupBoard(b, state, Board.COLOR_BLACK); var moves = GetMovesReverse(b, Board.COLOR_BLACK); for (int i = 0; i < moves.Length; i++) { var from = moves[i][0]; var to = moves[i][1]; // set player to black and set the position to the "precursor" state state.PlayerTurn = Board.COLOR_BLACK; MovePieceState(state, to, from); SetupBoard(b, state, Board.COLOR_BLACK); b->CurrentMove = 0; if(AreKingsTouching(b)) { // revert the state back to the original state state.PlayerTurn = Board.COLOR_WHITE; MovePieceState(state, from, to); continue; } // get moves from precursor state to any other available states var moveBitboard = Moves.GetMoves(b, from); var movesFromPreviousPos = Bitboard.Bitboard_BitList(moveBitboard); // We see if there is a way for black to get out of a forced mate by looking // for any moves that escape it. If white has a forced mate, the input state (original state) // is supposedly the best move black could make. // IF black can make moves tho states that aren't already explored, then they lead to a better // state for black, thus he can escape bool canEscape = false; for(int j=0; j < movesFromPreviousPos.Length; j++) { var backTo = movesFromPreviousPos[j]; var valid = Board.Make(b, from, backTo); if (valid) { Board.Unmake(b); // Check if this is a capture. We can't "un-capture" pieces so this would be a way out // for black. if (Bitboard.Get(b->Boards[Board.BOARD_WHITE], backTo)) { canEscape = true; break; } // find the hash for the next possible state state.PlayerTurn = Board.COLOR_WHITE; MovePieceState(state, from, backTo); var nextHash = state.Hash; state.PlayerTurn = Board.COLOR_BLACK; MovePieceState(state, backTo, from); // check if that is a known position if(!States.ContainsKey(nextHash)) { canEscape = true; break; } } } // If black can not escape the then moving to the original state is the best option black has. if (!canEscape) { var newState = new State(state); newState.NextState = originalHash; newState.DepthToMate++; newStates.Add(newState); } // revert the state back to the original state state.PlayerTurn = Board.COLOR_WHITE; MovePieceState(state, from, to); } // We messed with the state... alot. // Make sure there isn't a bug in the code and we just corrupted something :) if (originalHash != state.Hash) throw new Exception("State was altered"); } Board.Delete(b); return newStates; }
private unsafe void SetupBoard(BoardStruct* b, State state, byte playerTurn) { b->Boards[0] = 0; b->Boards[1] = 0; b->Boards[2] = 0; b->Boards[3] = 0; b->Boards[4] = 0; b->Boards[5] = 0; b->Boards[6] = 0; b->Boards[7] = 0; b->Castle = 0; b->EnPassantTile = 0; b->Hash = 0; Board.SetPiece(b, state.PieceLocation[0], state.Pieces[0] & 0x0F, state.Pieces[0] & 0xF0); Board.SetPiece(b, state.PieceLocation[1], state.Pieces[1] & 0x0F, state.Pieces[1] & 0xF0); Board.SetPiece(b, state.PieceLocation[2], state.Pieces[2] & 0x0F, state.Pieces[2] & 0xF0); Board.SetPiece(b, state.PieceLocation[3], state.Pieces[3] & 0x0F, state.Pieces[3] & 0xF0); b->AttacksBlack = Board.AttackMap(b, Board.COLOR_BLACK); b->AttacksWhite = Board.AttackMap(b, Board.COLOR_WHITE); b->PlayerTurn = playerTurn; b->Hash = b->Hash ^ Zob.Keys[Zobrist.ZOBRIST_SIDE, b->PlayerTurn]; Assert(b->Hash == state.Hash, "Hashes do not match"); }
private List<State> Generate4PieceMates(byte[] pieces) { var b = Board.Create(); var states = new List<State>(); byte p0 = pieces[0]; byte p1 = pieces[1]; byte p2 = pieces[2]; int i = 0; for (byte l0 = 0; l0 < 64; l0++) for (byte l1 = 0; l1 < 64; l1++) for (byte l2 = 0; l2 < 64; l2++) for (byte l3 = 0; l3 < 64; l3++) if (l0 != l1 && l0 != l2 && l0 != l3 && l1 != l2 && l1 != l3 && l2 != l3) { var state = new State(); state.Pieces = new byte[4]; state.PieceLocation = new byte[4]; state.PlayerTurn = Board.COLOR_BLACK; // set pieces state.Pieces[0] = p0; state.PieceLocation[0] = l0; state.Pieces[1] = p1; state.PieceLocation[1] = l1; state.Pieces[2] = p2; state.PieceLocation[2] = l2; state.Pieces[3] = p2; state.PieceLocation[3] = l2; state.DepthToMate = MAX; // set to max state.Hash = CalcHash(state); CheckIfMate(state, b); if (state.DepthToMate != 255) states.Add(state); i++; } Assert(i == 64 * 63 * 62); Board.Delete(b); var mateCount = states.Count(x => x.DepthToMate == 0); var stalemateCount = states.Count(x => x.DepthToMate == STALEMATE); return states; }
/*private bool IsValidState(State state) { SetupBoard(bs, state, state.PlayerTurn); if(AreKingsTouching(bs)) return false; var oppositePlayer = (state.PlayerTurn == Board.COLOR_WHITE) ? Board.COLOR_BLACK : Board.COLOR_WHITE; if(Board.IsChecked(bs, oppositePlayer) == 1) return false; return true; }*/ private bool Compare(State state1, State state2) { var a = state1.PieceLocation[0] == state2.PieceLocation[0]; var b = state1.PieceLocation[1] == state2.PieceLocation[1]; var c = state1.PieceLocation[2] == state2.PieceLocation[2]; var d = true; if(state1.Pieces[3] != 0 && state2.Pieces[3] != 0) d = state1.PieceLocation[3] == state2.PieceLocation[3]; var e = state1.PlayerTurn == state2.PlayerTurn; return a & b & c & d & e; }
/// <summary> /// Calculate hash of position after a move /// </summary> /// <param name="state"></param> /// <param name="moveFrom"></param> /// <param name="moveTo"></param> /// <returns></returns> private ulong CalcHash(State state, byte moveFrom, byte moveTo) { if (state.PieceLocation[0] == moveFrom) state.PieceLocation[0] = moveTo; if (state.PieceLocation[1] == moveFrom) state.PieceLocation[1] = moveTo; if (state.PieceLocation[2] == moveFrom) state.PieceLocation[2] = moveTo; if (state.PieceLocation[3] == moveFrom) state.PieceLocation[3] = moveTo; var hash = CalcHash(state); if (state.PieceLocation[0] == moveTo) state.PieceLocation[0] = moveFrom; if (state.PieceLocation[1] == moveTo) state.PieceLocation[1] = moveFrom; if (state.PieceLocation[2] == moveTo) state.PieceLocation[2] = moveFrom; if (state.PieceLocation[3] == moveTo) state.PieceLocation[3] = moveFrom; return hash; }
private ulong CalcHash(State state) { ulong hash = 0; hash ^= Zob.Keys[Zob.Index[state.Pieces[0]], state.PieceLocation[0]]; hash ^= Zob.Keys[Zob.Index[state.Pieces[1]], state.PieceLocation[1]]; hash ^= Zob.Keys[Zob.Index[state.Pieces[2]], state.PieceLocation[2]]; if(state.Pieces[3] != 0) hash ^= Zob.Keys[Zob.Index[state.Pieces[3]], state.PieceLocation[3]]; hash ^= Zob.Keys[Zobrist.ZOBRIST_SIDE, state.PlayerTurn]; return hash; }
public bool QueryStates(byte[] pieces) { Console.Write("Query Position (wK, wQ, bK):"); var line = Console.ReadLine(); if (line == "quit" || line == "exit") return false; var locations = line.Split(',').Select(x => Convert.ToByte(x.Trim())).ToArray(); var stateTemp = new State(); stateTemp.PieceLocation = locations; stateTemp.Pieces = pieces; stateTemp.PlayerTurn = Board.COLOR_WHITE; var hash = CalcHash(stateTemp); State state = null; if (States.ContainsKey(hash)) state = States[hash]; Console.WriteLine("Hash: " + state.Hash); Console.WriteLine("Depth to Mate: " + state.DepthToMate); Console.WriteLine("Position: " + state.PieceLocation[0] + ", " + state.PieceLocation[1] + ", " + state.PieceLocation[2] + ", " + state.PieceLocation[3]); if (States.ContainsKey(state.NextState)) { var next = States[state.NextState]; Console.WriteLine("Next Position: " + next.PieceLocation[0] + ", " + next.PieceLocation[1] + ", " + next.PieceLocation[2] + ", " + next.PieceLocation[3]); } Console.WriteLine(""); return true; }
public void MovePieceState(State state, byte moveFrom, byte moveTo) { if (state.PieceLocation[0] == moveFrom) state.PieceLocation[0] = moveTo; if (state.PieceLocation[1] == moveFrom) state.PieceLocation[1] = moveTo; if (state.PieceLocation[2] == moveFrom) state.PieceLocation[2] = moveTo; if (state.PieceLocation[3] == moveFrom) state.PieceLocation[3] = moveTo; state.Hash = CalcHash(state); }
public byte[] GetMove(State a, State b) { if (a.PieceLocation[0] != b.PieceLocation[0]) return new byte[] { a.PieceLocation[0], b.PieceLocation[0] }; if (a.PieceLocation[1] != b.PieceLocation[1]) return new byte[] { a.PieceLocation[1], b.PieceLocation[1] }; if (a.PieceLocation[2] != b.PieceLocation[2]) return new byte[] { a.PieceLocation[2], b.PieceLocation[2] }; if (a.PieceLocation[3] != b.PieceLocation[3]) return new byte[] { a.PieceLocation[3], b.PieceLocation[3] }; return new byte[2]; // no move }
/// <summary> /// Checks a position and determines if black is mated /// </summary> /// <param name="state"></param> /// <param name="b"></param> public void CheckIfMate(State state, BoardStruct* b) { SetupBoard(b, state, Board.COLOR_BLACK); var from = state.PieceLocation[2]; var moveBoard = Moves.GetMoves(b, from); var moves = Bitboard.Bitboard_BitList(moveBoard); // make sure the black king can't directly attack the white king, that's an illegal position if (AreKingsTouching(b)) return; bool isMate = true; for (int j = 0; j < moves.Length; j++) { var valid = Board.Make(b, from, moves[j]); if (valid) { Board.Unmake(b); isMate = false; break; } } if (isMate) { if (Board.IsChecked(b, Board.COLOR_BLACK) == 1) state.DepthToMate = 0; else state.DepthToMate = STALEMATE; } }
public List<State> CalculateWhite(List<State> stateSet) { // find all states where white can transition from a state into one of the input states in stateSet var newStates = new List<State>(); var b = Board.Create(); foreach(var state in stateSet) { var originalHash = state.Hash; state.PlayerTurn = Board.COLOR_WHITE; state.Hash = CalcHash(state); SetupBoard(b, state, Board.COLOR_WHITE); var moves = GetMovesReverse(b, Board.COLOR_WHITE); for (int i = 0; i < moves.Length; i++) { var from = moves[i][0]; var to = moves[i][1]; // set player to white and set the position to the "precursor" state state.PlayerTurn = Board.COLOR_WHITE; MovePieceState(state, to, from); SetupBoard(b, state, Board.COLOR_WHITE); b->CurrentMove = 0; // we must see the the position we are moving from already had black in check // Such a position could never actually occur, since can't enter check by himself bool wasChecked = Board.IsChecked(b, Board.COLOR_BLACK) == 1; if (!wasChecked) { var valid = Board.Make(b, from, to); if (valid) { var newState = new State(state); newState.NextState = originalHash; newState.DepthToMate++; newStates.Add(newState); } } // revert the state back to the original state state.PlayerTurn = Board.COLOR_BLACK; MovePieceState(state, from, to); } if (originalHash != state.Hash) throw new Exception("State was altered"); } Board.Delete(b); return newStates; }