public hist_rec(move Move, int Capture) { m_move = Move; m_capture = Capture; }
/// <summary> /// �D�n�禡, Ū��BOOK.DAT��ƨæs�Jmove[][]��Ƶ��c�餺 /// �b���B�n�S�O�`�N���O���Ъ��榡�O�ϥ�VSCCP���y�Ю榡 /// �ҥH�O�ϥ�VSCCP_BoardCodeEnum�ӸѪR�y���I����(Note:�D�`���n) /// </summary> public void Load() { string BookPath = string.Empty; StreamReader oReader = null; string CurrentLine = string.Empty; move[] CurrentLineMoves = null; string[] sp_Line = null; ArrayList al_Lines = new ArrayList(); try { //���JBOOK.DAT BookPath = Directory.GetParent(Directory.GetParent(Environment.CurrentDirectory).FullName) + @"\sys\"+"BOOK.DAT"; oReader = new StreamReader(new FileStream(BookPath,FileMode.Open), Encoding.Default); while((CurrentLine=oReader.ReadLine()) != null) { if(CurrentLine.StartsWith(";")) { //�H�����}�Y�������Ѧ�, ���B�z } else { //��ڭn�s�J���}�G������(Line) //ex:H2E2 B9C7 H0G2 H7F7 I0H0 H9G7 G3G4 C6C5 B0A2 G9E7 B2C2 A9B9 A0B0 B7B3 //���H�ťդ��ΥX��, �AParse�imove sp_Line = CurrentLine.Split(' '); CurrentLineMoves = new move[sp_Line.Length]; for(int i=0;i<sp_Line.Length;i++){CurrentLineMoves[i] = new move(sp_Line[i], typeof(VSCCP_BoardCodeEnum));} al_Lines.Add(CurrentLineMoves); } } //Convert ArrayList alLines back to Lines(move[][] type) m_Lines = new move[al_Lines.Count][]; for(int i=0;i<m_Lines.Length;i++) { m_Lines[i] = (move[])al_Lines[i]; } m_Length = al_Lines.Count; m_LoadFlag = true; } catch(Exception e) { m_Lines = null; m_Length = 0; m_LoadFlag = false; throw e; } finally { oReader.Close(); oReader = null; } }
public hist_rec() { m_move = new move(); m_capture = 0; }
/// <summary> /// 傳入棋步的建構子 /// </summary> /// <param name="m">傳入的合法棋步</param> public gen_rec(move m) { m_move = m; m_prior = 0; }
/// <summary> /// 傳入棋步及優先權數的建構子 /// </summary> /// <param name="m">傳入的合法棋步</param> /// <param name="p">傳入的優先權數</param> public gen_rec(move m, int p) { m_move = m; m_prior = p; }
/// <summary> /// �p���ٴѨB(�ӷ��Υت�)�Ҩϥ�, �@�ӴѨB�b�ѽL�i�H��4�չ�ٮy�� /// ���O�� ���`*1, �������*1, ������*1, ��g���*1 /// �D�n���}���w�b�ϥ�****�åB�n�`�N�什�w�ثe�O�ϥ�VSCCP�y�� /// </summary> /// <param name="m">�n�p�⪺�ѨB</param> /// <param name="mType">��٫��A</param> /// <returns>�p��X����ٴѨB</returns> public static move GetSymmetryMove(move m, MoveSymmetryTypeEnum mType) { int Origin_From = m.From; int Origin_Dest = m.Dest; int Symmetry_From = 0; int Symmetry_Dest = 0; switch(mType) { case MoveSymmetryTypeEnum.Normal: Symmetry_From = Origin_From; Symmetry_Dest = Origin_Dest; break; case MoveSymmetryTypeEnum.VerticalAxial: Symmetry_From = Origin_From + (constChess.SIZE_X - 1) - 2 * (Origin_From % constChess.SIZE_X); Symmetry_Dest = Origin_Dest + (constChess.SIZE_X - 1) - 2 * (Origin_Dest % constChess.SIZE_X); break; case MoveSymmetryTypeEnum.HorizontalAxial: Symmetry_From = Origin_From + ((constChess.SIZE_Y - 1) - 2 * (Origin_From / constChess.SIZE_X)) * constChess.SIZE_X; Symmetry_Dest = Origin_Dest + ((constChess.SIZE_Y - 1) - 2 * (Origin_Dest / constChess.SIZE_X)) * constChess.SIZE_X; break; case MoveSymmetryTypeEnum.Central: Symmetry_From = (constChess.BOARD_SIZE - 1) - Origin_From; Symmetry_Dest = (constChess.BOARD_SIZE - 1) - Origin_Dest; break; } return new move(Symmetry_From, Symmetry_Dest); }
/// <summary> /// 預設建構子 /// </summary> public gen_rec() { m_move = new move(); m_prior = 0; }
public static PlayerMoveTypeEnum DoHumanMove(Graphics g) { //建立合法棋步以供後續檢查用途 Gen(); if(!HumanMove_Selecting) { if(color[HumanMove_Dest]==side) { HumanMove_Selecting = true; HumanMove_From = HumanMove_Dest; DrawCell(g, (BoardCodeEnum)HumanMove_Dest, PieceStateEnum.SELECT); return PlayerMoveTypeEnum.FirstSelectingChess; } return PlayerMoveTypeEnum.OtherIllegalMove; } else { if(HumanMove_Dest!=HumanMove_From){DrawCell(g, (BoardCodeEnum)HumanMove_From, PieceStateEnum.NORMAL);} if(color[HumanMove_Dest]==side) { HumanMove_From = HumanMove_Dest; DrawCell(g, (BoardCodeEnum)HumanMove_Dest, PieceStateEnum.SELECT); return PlayerMoveTypeEnum.SameColorAndReSelectNew; } else { newmove = new move(HumanMove_From, HumanMove_Dest); for(int i=gen_begin[ply];i<gen_end[ply];i++) { if(gen_dat[i].Move.From==newmove.From && gen_dat[i].Move.Dest==newmove.Dest) { //Reset Global HumanMove Variable HumanMove_Selecting = false; HumanMove_From = -1; HumanMove_Dest = -1; return PlayerMoveTypeEnum.Normal; } } DrawCell(g, (BoardCodeEnum)HumanMove_From, PieceStateEnum.SELECT); return PlayerMoveTypeEnum.OtherIllegalMove; } } }
/// <summary> /// �����մѨB�O�_�۵�(�ӷ��I=�ӷ��I, �ت��I=�ت��I) /// </summary> /// <param name="m1">�ѨB1</param> /// <param name="m2">�ѨB2</param> /// <returns>bool</returns> public static bool Compare(move m1, move m2) { bool bReturn = false; if((m1.From == m2.From) && (m1.Dest == m2.Dest)){bReturn = true;} return bReturn; }
/* Search game tree by alpha-beta algorith */ public static int AlphaBeta(int alpha, int beta, int depth) { int i, __value, best; if(depth==0){return Quiescence(alpha, beta);} if(!Gen()){return -1000+ply;} if(follow_pv!=0){Check_pv();} Sort(); best = constChess.INFINITY * -1; for(i=gen_begin[ply];i<gen_end[ply] && best<beta;i++) { if(best>alpha){alpha = best;} if(MakeMove(gen_dat[i].Move)) { __value = 1000-ply; } else { __value = -1 * (AlphaBeta(-1 * beta, -1 * alpha, depth-1)); } UnMakeMove(); if(__value>best) { history[gen_dat[i].Move.From][gen_dat[i].Move.Dest] = depth; best = __value; if(ply==0){newmove = gen_dat[i].Move;} pv[ply] = gen_dat[i].Move; } } return best; }
/* 30步內不可走相同的步法 */ public static bool CheckMoveLoop() { bool b; int[] hdmap = new int[constChess.MAXREP+1]; int c, f, i, j, k, m, p; move cm = new move(); /* 沒有攻擊子時, 不限制重覆走相同步數 */ if((hdp<3) || (materialnumber[xside][(int)PieceTypeEnum.ROOK]+materialnumber[xside][(int)PieceTypeEnum.CANNON]+materialnumber[xside][(int)PieceTypeEnum.KNIGHT]+materialnumber[xside][(int)PieceTypeEnum.PAWN]==0)){return false;} for(i=0;i<constChess.MAXREP;i++){hdmap[i] = 0;} m = (hdp>constChess.MAXREP) ? constChess.MAXREP : hdp; c = 0; i = 0; k = 0; while(i<m) { #region While Loop i<m if(hist_dat[hdp-1-i].Capture!=(int)PieceTypeEnum.EMPTY){return false;} if(hdmap[constChess.MAXREP-i]==0) { c++; hdmap[constChess.MAXREP-i] = c; p = hist_dat[hdp-1-i].Move.Dest; f = hist_dat[hdp-1-i].Move.From; j = i+1; while(j<m) { #region While Loop j<m if(f==hist_dat[hdp-1-j].Move.Dest) { f = hist_dat[hdp-1-j].Move.From; hdmap[constChess.MAXREP-j] = c; if(p==f) { if(k<j){k = j;} break; } } j++; #endregion } if(j>m){break;} } i++; if(i>2 && i==k) { b = Attack(hist_dat[hdp-1].Move.Dest, xside); if(!b) { cm = hist_dat[hdp-1].Move; UnMakeMove(); b = Attack(cm.From, side); MakeMove(cm); if(b){return false;} } return true; } #endregion } return false; }
static controller() { ZeroPoint = new PointF(20f, 20f); htPieceMap = new Hashtable(12); newmove = new move(); for(int i=0;i<gen_dat.Length;i++){gen_dat[i] = new gen_rec();} for(int i=0;i<hist_dat.Length;i++){hist_dat[i] = new hist_rec();} }
public static bool MoveSave(int from, int dest) { move ms; bool bRtnMoveSave; if(piece[dest]==(int)PieceTypeEnum.KING){return true;} ms = new move(from, dest); MakeMove(ms); bRtnMoveSave = IsInCheck(xside); if(!bRtnMoveSave) { bRtnMoveSave = CheckMoveLoop(); } UnMakeMove(); return !bRtnMoveSave; }
public static bool MakeMove(move m) { int from, dest, p; //取得棋步來源點 from = m.From; //取得棋步目的點 dest = m.Dest; //取得棋步目的點的棋子型態 p = piece[dest]; if(p!=(int)PieceTypeEnum.EMPTY){materialnumber[xside][p]--;} //棋步存入歷史棋步記錄中(hist_dat) hist_dat[hdp].Move = m; //在更新目前要被移入棋子的目的點資料之前先將該點棋子型態記錄起來(被吃子型態) //顏色可由來回手判別得知.. 所以不需記錄下來 hist_dat[hdp].Capture = p; //更新實際棋盤對應陣列資料 //1.來源點棋子型態==>目的點棋子型態 //2.來源點棋子型態設定成無棋子型態 Clear //3.來源點棋子顏色==>目的點棋子顏色 //4.來源點棋子顏色設定成無棋子顏色 Clear piece[dest] = piece[from]; piece[from] = (int)PieceTypeEnum.EMPTY; color[dest] = color[from]; color[from] = (int)PieceColorEnum.EMPTY; //相關索引註標進1 hdp++; ply++; //執子方, 等待方註標交換 side = xside; xside = 1-xside; //傳回值加上判別是否已ChechMate(棋步目的點為KING) //所以若傳回True表示遊戲已結束(已有勝負出現) return (p == (int)PieceTypeEnum.KING); }
public static void InitGen() { #region 棋局必須初始化的變數 gen_begin[0] = 0; ply = 0; hdp = 0; #endregion #region 開局庫必須初始化的變數 NumberOfTotalMoves = 0; History_For_BookCheck = new move[4][]{ new move[constChess.HISTORY_TO_OPENING_BOOK_STACK], new move[constChess.HISTORY_TO_OPENING_BOOK_STACK], new move[constChess.HISTORY_TO_OPENING_BOOK_STACK], new move[constChess.HISTORY_TO_OPENING_BOOK_STACK] }; for(int i=0;i<History_For_BookCheck.Length;i++) { for(int j=0;j<History_For_BookCheck[0].Length;j++) { History_For_BookCheck[i][j] = new move(); } } #endregion #region QuickSort必須初始化的變數 history = new int[constChess.BOARD_SIZE][]{ new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE], new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE], new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE], new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE], new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE], new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE], new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE], new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE], new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE], new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE],new int[constChess.BOARD_SIZE] }; pv = new move[constChess.HIST_STACK]; for(int i=0;i<pv.Length;i++) { pv[i] = new move(); } #endregion }
/// <summary> /// 在開局庫內比對目前棋步組是否有相同的棋局, 若有則使用開局庫的棋步來代替 /// 電腦方思考結果 /// </summary> /// <returns>bool (True:有找到, False:沒有找到)</returns> public static bool GetBook() { int k=0, sk=0; bool MatchOpeningBook = false; move MatchedNextMove = null; if(BookDataHasRetire){return false;} //開局庫已沒用處時(已對應不到相同棋步了) if(!ReadBook()){return false;} if(NumberOfTotalMoves == 0) //第0步來查詢開局庫, 表示第一手由電腦方走子 { #region 第一手由電腦方走子時之初始化動作 if(computerside == (int)PieceColorEnum.DARK) { sk = 2; //Dark Side } else { sk = 0; //White Side } k = 0; MatchOpeningBook = true; MatchedNextMove = BookData.Lines[0][0]; #endregion } else { //要比對所有開局庫的棋步與現在棋盤上走子的全部棋步 //檢查有沒有合乎的可無電腦方走子直接套用(即不用再AlphaBeta搜尋) for(int i=0;i<BookData.Length;i++) //一個Loop表示開局庫棋譜內的一行 { int CurrentLine_MovesCount = BookData.Lines[i].Length; #region 檢查是否已走子到超出了此行開局庫棋譜所包含的棋步總數,若已超出就無法再比對此行開局庫棋譜... if(CurrentLine_MovesCount > NumberOfTotalMoves) { #region 四種對稱棋步座標都要比對一次 for(sk=0;sk<4;sk++) { #region 實際最內部的比對動作 for(k=0,MatchOpeningBook=true;k<NumberOfTotalMoves;k++) { //若中途有出現不符合的棋步, 即表示此開局庫不符合目前盤面所走步法, 不用再比對!! if(!move.Compare(History_For_BookCheck[sk][k], BookData.Lines[i][k])) { MatchOpeningBook = false; break; } } if(MatchOpeningBook){break;} //若走完整個內部檢查迴圈後得到符合的棋步, 就可跳出整個三層迴圈了 #endregion } #endregion if(MatchOpeningBook) { MatchedNextMove = BookData.Lines[i][k]; break; }//若走完整個內部檢查迴圈後得到符合的棋步, 就可跳出整個三層迴圈了 } #endregion } } #region 開局庫內若有找到符合的棋譜, 把符合的棋譜下一步棋步設定給電腦方目前要走子的步法內 if((MatchOpeningBook)&&(MatchedNextMove!=null)) { newmove = move.GetSymmetryMove(MatchedNextMove, (MoveSymmetryTypeEnum)sk); } #endregion return MatchOpeningBook; }