/* * Gnome Nine Mens Morris * Written by Dirk Farin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "board.hh" #include #include #include using namespace std; #include #include extern ofstream err; char milltab_short[16][3] = { { 16,17,18 }, { 8, 9,10 }, { 0, 1, 2 }, { 6, 5, 4 }, { 14,13,12 }, { 22,21,20 }, { 16,23,22 }, { 8,15,14 }, { 0, 7, 6 }, { 2, 3, 4 }, { 10,11,12 }, { 18,19,20 }, { 17, 9, 1 }, { 3,11,19 }, { 5,13,21 }, { 7,15,23 } }; int neighbour[3*8][4] = { { 1, 7,-1,-1 }, { 0, 2, 9,-1 }, { 1, 3,-1,-1 }, { 2, 4,11,-1 }, { 3, 5,-1,-1 }, { 4, 6,13,-1 }, { 5, 7,-1,-1 }, { 0, 6,15,-1 }, { 9,15,-1,-1 }, { 8, 1,10,17 }, { 9,11,-1,-1 }, { 3,10,12,19 }, { 11,13,-1,-1 }, { 5,12,14,21 }, { 13,15,-1,-1 }, { 23,14, 8, 7 }, { 17,23,-1,-1 }, { 16,18, 9,-1 }, { 17,19,-1,-1 }, { 18,11,20,-1 }, { 19,21,-1,-1 }, { 13,22,20,-1 }, { 21,23,-1,-1 }, { 16,15,22,-1 } }; char milltab[3*8][2][2]; void InitMillTab() { int num[3*8]; for (int i=0;i<3*8;i++) num[i]=0; for (int i=0;i<16;i++) { int a = milltab_short[i][0]; int b = milltab_short[i][1]; int c = milltab_short[i][2]; assert(num[a]<=1); assert(num[b]<=1); assert(num[c]<=1); milltab[a][num[a]][0] = b; milltab[a][num[a]][1] = c; milltab[b][num[b]][0] = a; milltab[b][num[b]][1] = c; milltab[c][num[c]][0] = a; milltab[c][num[c]][1] = b; num[a]++; num[b]++; num[c]++; } #if 0 for (int i=0;i<3*8;i++) { cout << i << "," << ((int)milltab[i][0][0]) << "," << ((int)milltab[i][0][1]) << " "; cout << i << "," << ((int)milltab[i][1][0]) << "," << ((int)milltab[i][1][1]) << endl; } #endif } Move::Move(const char* descr) { start= -1; take = -1; end = (descr[0]-'a')<<3; end |= descr[1]-'1'; int p=2; if (isalpha(descr[p])) { start=end; end = (descr[p]-'a')<<3; end |= descr[p+1]-'1'; p+=2; } if (descr[p]=='-') { take = (descr[p+1]-'a')<<3; take |= descr[p+2]-'1'; } } void Board::Init() { for (int n=0;n<3*8;n++) board[n]=EMPTY; next = WHITE; n_white = 0; n_black = 0; ply = 0; } void Board::DoMove(const Move& m) { // start field must contain own piece if (m.start>=0) { assert(board[m.start] == next); board[m.start]=EMPTY; } // end field must be empty assert(board[m.end] == EMPTY); board[m.end]=next; if (m.take>=0) { assert(board[m.take]== -next); board[m.take]=EMPTY; } if (next==WHITE) { if (m.start<0) n_white++; if (m.take>=0) n_black--; } else { if (m.start<0) n_black++; if (m.take>=0) n_white--; } next = -next; ply++; } void Board::MoveToString(const Move& m,char* buf) const { char* p = buf; if (m.start>=0) { *p++ = (m.start>>3)+'a'; *p++ = (m.start&7)+'1'; } assert(m.end>=0); *p++ = (m.end>>3)+'a'; *p++ = (m.end&7)+'1'; if (m.take>=0) { *p++ = '-'; *p++ = (m.take>>3)+'a'; *p++ = (m.take&7)+'1'; } *p = 0; } bool Board::CurrentHasLost() const { if (ply<2*9) return false; if (next==WHITE && n_white==2) return true; if (next==BLACK && n_black==2) return true; return false; } bool Board::OpponentHasLost() const { if (ply<2*9) return false; if (next==WHITE && n_black==2) return true; if (next==BLACK && n_white==2) return true; return false; } int Board::GenMoves(Move* p_result, int maxMoves) const { int num=0; if (ply < 2*9) { for (int n=0;n<3*8;n++) if (board[n]==EMPTY) { assert(num=0;i++) if (board[neighbour[n][i]]==EMPTY) { int dest = neighbour[n][i]; p_result[num].start=n; p_result[num].end=dest; if (WouldCloseMill(n,dest)) { assert(num < maxMoves-9); num += GenTakes(&p_result[num]); } else { p_result[num].take=-1; num++; } } } } else // may_jump == true { for (int n=0;n<3*8;n++) if (board[n]==next) { assert(num0); return num; } int Board::Freedom(int n) const { int cnt=0; for (int i=0;i<4 && neighbour[n][i]>=0;i++) if (board[neighbour[n][i]]==EMPTY) cnt++; return cnt; }