// MfcKatsunariDoc.cpp : CMfcKatsunariDoc クラスの動作の定義を行います。 // #include "stdafx.h" #include "MfcKatsunari.h" #include "MfcKatsunariDoc.h" #include "SetupDlg.h" #include "process.h" #include "mmsystem.h" static int TimeForKatsunari[3]; static HWND hWnd; #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMfcKatsunariDoc IMPLEMENT_DYNCREATE(CMfcKatsunariDoc, CDocument) BEGIN_MESSAGE_MAP(CMfcKatsunariDoc, CDocument) //{{AFX_MSG_MAP(CMfcKatsunariDoc) ON_COMMAND(ID_NEWGAME, OnNewgame) ON_UPDATE_COMMAND_UI(ID_PASS, OnUpdatePass) ON_COMMAND(ID_PASS, OnPass) ON_UPDATE_COMMAND_UI(ID_UNDO, OnUpdateUndo) ON_COMMAND(ID_UNDO, OnUndo) ON_COMMAND(ID_EVALUATE, OnEvaluate) ON_UPDATE_COMMAND_UI(ID_REDO, OnUpdateRedo) ON_COMMAND(ID_REDO, OnRedo) ON_UPDATE_COMMAND_UI(ID_FILE_OPEN, OnUpdateFileOpen) ON_UPDATE_COMMAND_UI(ID_GO_KATSUNARI, OnUpdateGoKatsunari) ON_UPDATE_COMMAND_UI(ID_NEWGAME, OnUpdateNewgame) ON_COMMAND(ID_LASTVALUE, OnLastvalue) ON_UPDATE_COMMAND_UI(ID_LASTVALUE, OnUpdateLastvalue) ON_UPDATE_COMMAND_UI(ID_EVALUATE, OnUpdateEvaluate) ON_COMMAND(IDM_SET_COLOR, OnSetColor) ON_UPDATE_COMMAND_UI(IDM_SET_COLOR, OnUpdateSetColor) ON_UPDATE_COMMAND_UI(ID_CONTINUE, OnUpdateContinue) ON_COMMAND(ID_CONTINUE, OnContinue) ON_UPDATE_COMMAND_UI(ID_STOP, OnUpdateStop) ON_COMMAND(ID_STOP, OnStop) ON_COMMAND(ID_MATTA, OnMatta) ON_UPDATE_COMMAND_UI(ID_MATTA, OnUpdateMatta) ON_COMMAND(ID_GO_KATSUNARI, OnGoKatsunari) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMfcKatsunariDoc クラスの構築/消滅 CMfcKatsunariDoc::CMfcKatsunariDoc() { // TODO: この位置に1回だけ構築用のコードを追加してください。 Initialized=FALSE; DispLastValue=0; Message[0]='\0'; isCommPortOpen=FALSE; R=G=B=0; playout=500; komi=7; } CMfcKatsunariDoc::~CMfcKatsunariDoc() { } BOOL CMfcKatsunariDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; FILE *fp; char line[3]; boardSize = BOARD_SIZE; pureBoardSize = PURE_BOARD_SIZE; if( (fopen_s(&fp, "mctsgo.ini", "r")) == 0 ){ if( fgets( line, 3, fp ) != NULL){ if(strcmp(line, "9") == 0 || strcmp(line, "9\n") == 0){ boardSize = 11; pureBoardSize = 9; }else if(strcmp(line, "13") == 0 || strcmp(line, "13\n") == 0){ boardSize = 15; pureBoardSize = 13; } } } fclose(fp); int x,y; for(y=0;yGetFilePath(); if (ar.IsStoring()) { saveScore(FileName); } else { loadScore(FileName); move=1; UndoDepth=scoreCount; ClearGameBoard(boardSize); SetHandicapStoneGameBoard(getHandicap()); color=getHandicap()<=1 ? BLACK : WHITE; hama[BLACK]=hama[WHITE]=0; PlayLog[0].hama[BLACK]=hama[BLACK]; PlayLog[0].hama[WHITE]=hama[WHITE]; PlayLog[0].x=PlayLog[0].y=0; for(i=1;i 0) sprintf_s(buf,sizeof(buf),"盤面 黒 %d 目半勝ち。",keisei-1); else if(keisei <= 0) sprintf_s(buf, sizeof(buf), "盤面 白 %d 目半勝ち。", (-keisei)); else sprintf_s(buf, sizeof(buf), "盤面 牛角。"); ((CFrameWnd *)(AfxGetApp()->m_pMainWnd))->GetActiveView()->MessageBox(buf); Teban=REPLAY; // OnFileSaveAs(); } void Run(void *p) { int x,y,e; int color,move,kind,ko_x,ko_y,ko_move; int po,km; color=((CMfcKatsunariDoc *)p)->color; move=((CMfcKatsunariDoc *)p)->move; ko_x=((CMfcKatsunariDoc *)p)->ko_x; ko_y=((CMfcKatsunariDoc *)p)->ko_y; ko_move=((CMfcKatsunariDoc *)p)->ko_num; if (color==BLACK) { kind=((CMfcKatsunariDoc *)p)->KindBlack; } else { kind=((CMfcKatsunariDoc *)p)->KindWhite; } if (((CMfcKatsunariDoc *)p)->EndFlag) { return; } po=((CMfcKatsunariDoc *)p)->playout; km=((CMfcKatsunariDoc *)p)->komi; char *msg=selectNextMove( &x, &y, &e, color, move/*, kind*/, ko_x, ko_y, ko_move , ((CMfcKatsunariDoc *)p)->pureBoardSize, po, km); /* select.c */ copyEvaluation(((CMfcKatsunariDoc *)p)->Value, ((CMfcKatsunariDoc *)p)->boardSize); ::PostMessage(hWnd,WM_NEXT_MOVE,x,y); _endthread(); // Profileをとるときコメントアウト } void Comm(void *p) { int x,y; CMfcKatsunariDoc *pDoc=(CMfcKatsunariDoc *)p; while(!receivexy(&x,&y) && !pDoc->EndFlag) { Sleep(200); } if (!pDoc->EndFlag) { ::PostMessage(hWnd,WM_NEXT_MOVE,x,y); } _endthread(); } void CMfcKatsunariDoc::GoKatsunari() { hWnd=((CFrameWnd *)(AfxGetApp()->m_pMainWnd))->GetActiveView()->m_hWnd; hThread=(HANDLE)_beginthread(Run,0,(void *)this); // Profileをとるときコメントアウト // Run((void *)this); // Profileをとるときのため } void CMfcKatsunariDoc::GoComm() { hWnd=((CFrameWnd *)(AfxGetApp()->m_pMainWnd))->GetActiveView()->m_hWnd; hThread=(HANDLE)_beginthread(Comm,0,(void *)this); } void CMfcKatsunariDoc::NextMove(int x,int y) { int win = 0; if (EndFlag) { return; } if (Teban==REPLAY) { return; } hWnd=((CFrameWnd *)(AfxGetApp()->m_pMainWnd))->GetActiveView()->m_hWnd; // 手を打ったらリドゥは無効 UndoDepth=0; hThread=NULL; EndFlag=0; // 記録をとる。 if (x==0) { win = y; y = 0; recordScore(0,0,color,move); } else { if (checkSetStoneGameBoard(x,y,color,move)!=TRUE) { char buf[256]; sprintf_s(buf, sizeof(buf), "相手の手が変です。(%d,%d).",x,y); MessageBox(AfxGetMainWnd()->m_hWnd,buf,"通信エラー",MB_OK); } recordScore(x,y,color,move); } PlayLog[move].x=x; PlayLog[move].y=y; // ファイルにログを出しておく for DEBUG saveScore("PlayLog.sgf"); // 相手に送りつける if ((color==WHITE && BWSide[BLACK]==COMM) || (color==BLACK && BWSide[WHITE]==COMM) ) { if (!sendxy(x,y)) { MessageBox(AfxGetMainWnd()->m_hWnd,"SendXYに失敗しました。","通信エラー",MB_OK); } } // 計時 unsigned int Now=(unsigned int)GetTickCount64(); Time[color]+=Now-LastTime; TimeForKatsunari[color]=Time[color]; LastTime=Now; // 最後の手の書き換え LastMove[color]=move; LastMoveX[color]=x; LastMoveY[color]=y; // 盤面を書き換える。 CUpdateKatsunari UpdateData; UpdateData.OldX=LastX; UpdateData.OldY=LastY; memcpy(UpdateData.OldBan,Ban,sizeof(Ban)); int PreX=LastX; LastX=x; LastY=y; if(x!=0&&y!=0){ hama[color] +=SetStoneOnGameBoard(x,y,color,move); PlayLog[move].hama[BLACK]=hama[BLACK]; PlayLog[move].hama[WHITE]=hama[WHITE]; memcpy(UpdateData.NewBan,Ban,sizeof(Ban)); } UpdateAllViews(NULL,DispLastValue,&UpdateData); // x==0 は パス。 if (win != 0 || x==0 && PreX==0 || move>500) { // パス2連続 or 500手オーバー GameOver(win); } else { int preTeban=BWSide[color]; // 次の手。 if (color==WHITE) { color=BLACK; } else { color=WHITE; } move++; Teban=BWSide[color]; if (Teban==HUMAN && LastX==0 && preTeban==COMPUTER) { MessageBox(AfxGetMainWnd()->m_hWnd,"パスしました","コンピュータ"/*"名無し"*/,MB_OK); } if (LastX!=0) { sndPlaySound((const char *)lpSound,SND_ASYNC|SND_MEMORY); } Play(); } } void CMfcKatsunariDoc::Play() { switch(Teban) { case HUMAN: // 単純に入力を待てば良い break; case COMM: // スレッドを起こして、通信を待つ GoComm(); break; case COMPUTER: // スレッドを起こして、名無しに考えさせる。 GoKatsunari(); break; } } void LoadInitialFileThread(void *p) { CMfcKatsunariDoc *pDoc=(CMfcKatsunariDoc *)p; ::PostMessage(hWnd,WM_INITIAL_LOADED,8,0); initAll(); ::PostMessage(hWnd,WM_INITIAL_LOADED,0,0); pDoc->Initialized=TRUE; _endthread(); } void CMfcKatsunariDoc::LoadInitialFiles() { hWnd=((CFrameWnd *)(AfxGetApp()->m_pMainWnd))->GetActiveView()->m_hWnd; _beginthread(LoadInitialFileThread,0,(void *)this); } void CMfcKatsunariDoc::OnNewgame() { // CommPortが開いていたら一旦閉じる if(isCommPortOpen){ isCommPortOpen=FALSE; closecom(); } if (hThread!=NULL) { EndFlag=1; AfxGetMainWnd()->EnableWindow(FALSE); while(WaitForSingleObject(hThread,100)==WAIT_TIMEOUT) { AfxGetThread()->PumpMessage(); } AfxGetMainWnd()->EnableWindow(TRUE); } CSetupDlg SetupDlg; if (SetupDlg.DoModal()==IDCANCEL) { return; } playout = SetupDlg.m_playout; komi = SetupDlg.m_komi; port=1; if (SetupDlg.m_TebanBlack==COMM+1) { port=2; SetupDlg.m_TebanBlack=COMM; } if (SetupDlg.m_TebanWhite==COMM+1) { port=2; SetupDlg.m_TebanWhite=COMM; } if(SetupDlg.m_TebanWhite==COMM && SetupDlg.m_TebanBlack==COMM) { MessageBox(AfxGetMainWnd()->m_hWnd,"両方通信にすることはできません。","警告",MB_OK); return; } if( (SetupDlg.m_TebanWhite==COMM || SetupDlg.m_TebanBlack==COMM ) && SetupDlg.m_Handycap>0) { MessageBox(AfxGetMainWnd()->m_hWnd,"通信対戦では、手合いは互い先のみとなります。","警告",MB_OK); return; } if(SetupDlg.m_TebanBlack == COMM || SetupDlg.m_TebanWhite == COMM){ if (!initcom(port)) { MessageBox(AfxGetMainWnd()->m_hWnd,"InitComに失敗しました。","通信エラー",MB_OK); return; } isCommPortOpen=TRUE; } BWSide[BLACK]=SetupDlg.m_TebanBlack; BWSide[WHITE]=SetupDlg.m_TebanWhite; ClearGameBoard(boardSize); for(int y=0;ym_hWnd,"NewGameに失敗しました。","通信エラー",MB_OK); return; } } else if(SetupDlg.m_TebanWhite == COMM){ if (!newgame(BLACK)) { MessageBox(AfxGetMainWnd()->m_hWnd,"NewGameに失敗しました。","通信エラー",MB_OK); return; } } EndFlag=0; if (SetupDlg.m_KindBlack.IsEmpty()) { KindBlack=0; } else { KindBlack=SetupDlg.m_KindBlack[0]-'0'; // 名無しの気分(^^; } if (SetupDlg.m_KindWhite.IsEmpty()) { KindWhite=0; } else { KindWhite=SetupDlg.m_KindWhite[0]-'0'; // 名無しの気分(^^; } move=1; UndoDepth=0; hama[BLACK]=hama[WHITE]=0; Time[BLACK]=Time[WHITE]=0; TimeForKatsunari[BLACK]=TimeForKatsunari[WHITE]=0; LastMove[BLACK]=LastMove[WHITE]=0; LastMoveX[BLACK]=LastMoveX[WHITE]=0; LastMoveY[BLACK]=LastMoveY[WHITE]=0; LastTime=(unsigned int)GetTickCount64(); hThread=NULL; UpdateAllViews(NULL); Play(); } void CMfcKatsunariDoc::OnUpdatePass(CCmdUI* pCmdUI) { pCmdUI->m_bEnableChanged = TRUE; pCmdUI->Enable(Teban==HUMAN); } void CMfcKatsunariDoc::OnPass() { hWnd=((CFrameWnd *)(AfxGetApp()->m_pMainWnd))->GetActiveView()->m_hWnd; ::PostMessage(hWnd,WM_NEXT_MOVE,0,0); } void CMfcKatsunariDoc::OnUpdateRedo(CCmdUI* pCmdUI) { pCmdUI->m_bEnableChanged = TRUE; pCmdUI->Enable(Teban==REPLAY && UndoDepth>0); } void CMfcKatsunariDoc::OnRedo() { move+=1; replayFromScoreGameBoard(move-1); // 相手の手番になる if (color==WHITE) color=BLACK; else color=WHITE; // 最後の手の書き換え SetLastMoveFromReplay(); Teban=REPLAY; UndoDepth-=1; UpdateAllViews(NULL); } void CMfcKatsunariDoc::OnUpdateUndo(CCmdUI* pCmdUI) { pCmdUI->m_bEnableChanged = TRUE; pCmdUI->Enable(Teban==REPLAY && move>1); } void CMfcKatsunariDoc::OnUndo() { move-=1; replayFromScoreGameBoard(move-1); // 相手の手番になる if (color==WHITE) color=BLACK; else color=WHITE; // 最後の手の書き換え SetLastMoveFromReplay(); Teban=REPLAY; UndoDepth+=1; UpdateAllViews(NULL); } void CMfcKatsunariDoc::OnUpdateEvaluate(CCmdUI* pCmdUI) { pCmdUI->m_bEnableChanged = TRUE; pCmdUI->Enable(Teban==HUMAN || Teban==REPLAY); } void CMfcKatsunariDoc::OnEvaluate() { int tmpBoard[BOARD_SIZE][BOARD_SIZE]; memcpy(tmpBoard,Ban,sizeof(Ban)); CUpdateKatsunari UpdateData; UpdateData.OldX=0; UpdateData.OldY=0; memcpy(UpdateData.OldBan,Ban,sizeof(Ban)); int keisei = copyStatus(Ban, pureBoardSize); // 形勢表示 memcpy(UpdateData.NewBan,Ban,sizeof(Ban)); UpdateAllViews(NULL,DispLastValue,&UpdateData); keisei = keisei-komi/*+hama[BLACK]-hama[WHITE]*/; char buf[80]; if(keisei > 0){ sprintf_s(buf, sizeof(buf),"盤面 黒 %d 目半勝ち。",keisei-1); } else if(keisei <= 0){ sprintf_s(buf, sizeof(buf),"盤面 白 %d 目半勝ち。", (-keisei)); } else { sprintf_s(buf, sizeof(buf),"盤面 牛角。"); } MessageBox(AfxGetMainWnd()->m_hWnd,buf,"形勢表示中",MB_OK); memcpy(Ban,tmpBoard,sizeof(Ban)); UpdateAllViews(NULL); } void CMfcKatsunariDoc::OnUpdateFileOpen(CCmdUI* pCmdUI) { pCmdUI->m_bEnableChanged = TRUE; pCmdUI->Enable(Teban!=COMPUTER && Teban!=COMM && Initialized); } int CMfcKatsunariDoc::_getKeyValue(FILE *fp,char *key,char *val) { int c; char *kp, *vp; /* key[val] */ kp = key; vp = val; do { c = fgetc(fp); if(c == ')') return 1; if(c == EOF) return -1; } while(c < 'A' || 'Z' < c); /* key[ */ *kp++ = (char) c; do { c = fgetc(fp); if(c == EOF) return -2; *kp++ = (char) c; } while(c != '['); *(--kp) = '\0'; /* val] */ do { c = fgetc(fp); if(c == EOF) return -3; *vp++ = (char) c; } while(c != ']'); *(--vp) = '\0'; return 0; } int CMfcKatsunariDoc::saveScore(const char* fn ) { int i, x, y; FILE *fp; if ((fopen_s(&fp, fn, "w+")) != 0) fp = stdout; /* GM: Game種別(1は囲碁) */ /* FF: SGFのバージョン */ fprintf( fp, "(;GM[1]FF[1]" ); /* SZ: Size of Board */ fprintf( fp, "SZ[%d]", initialSetting.boardSize ); /* PB: Player Black */ /* PW: Player White */ if( initialSetting.blackSide == HUMAN ){ if (initialSetting.blackName == NULL) { fprintf( fp, "PB[human]" ); }else if( strcmp( initialSetting.blackName, " 人間" ) == 0 ){ fprintf( fp, "PB[human]" ); } else { fprintf( fp, "PB[%s]", initialSetting.blackName ); } }else{ fprintf( fp, "PB[katsunari]" ); } if( initialSetting.whiteSide == HUMAN ){ if (initialSetting.whiteName == NULL) { fprintf( fp, "PW[human]" ); }else if( strcmp( initialSetting.whiteName, " 人間" ) == 0 ){ fprintf( fp, "PW[human]" ); } else { fprintf( fp, "PW[%s]", initialSetting.whiteName ); } }else{ fprintf( fp, "PW[katsunari]" ); } /* その他の項目 */ fprintf( fp, "RE[]\n" ); /* RE: Result */ fprintf( fp, "DT[]" ); /* DT: Date */ fprintf( fp, "PC[]" ); /* PC: Place */ fprintf( fp, "EV[]" ); /* EV: Event */ fprintf( fp, "GN[]" ); /* GN: Game Name */ fprintf( fp, "TM[]" ); /* TM: Time for each player */ fprintf( fp, "RU[Japanese]" ); /* RU: Rule */ if( initialSetting.handicap > 0 ){ /* HA: Handicap */ fprintf( fp, "\nHA[%d]", initialSetting.handicap ); /* AB: Places of each stones in Handicap Game */ switch( initialSetting.handicap ){ case 2 : fprintf( fp, "AB[jd][dj]\n" ); break; case 3 : fprintf( fp, "AB[jd][dj][jj]\n" ); break; case 4 : fprintf( fp, "AB[jd][dj][jj][dd]\n" ); break; case 5 : fprintf( fp, "AB[jd][dj][jj][dd][gg]\n" ); break; case 6 : fprintf( fp, "AB[jd][dj][jj][dd][jg][dg]\n" ); break; case 7 : fprintf( fp, "AB[jd][dj][jj][dd][jg][dg][gg]\n" ); break; case 8 : fprintf( fp, "AB[jd][dj][jj][dd][jg][dg][gd][gj]\n" ); break; case 9 : fprintf( fp, "AB[jd][dj][jj][dd][jg][dg][gd][gj][gg]\n" ); break; } }else{ /* KM: Komi */ fprintf( fp, "KM[5.5]\n" ); } for (i=1;i<=scoreCount;i++) { /* x = (1 <= score[i].y && score[i].y <= 19)? (score[i].y + 'a' - 1): 't'; y = (1 <= score[i].x && score[i].x <= 19)? (score[i].x + 'a' - 1): 't'; */ y = (1 <= score[i].y && score[i].y <= pureBoardSize/*PURE_BOARD_SIZE*/)? (score[i].y + 'a' - 1): 't'; x = (1 <= score[i].x && score[i].x <= pureBoardSize/*PURE_BOARD_SIZE*/)? (score[i].x + 'a' - 1): 't'; if(score[i].color == BLACK){ fprintf(fp, ";B[%c%c]", x, y); } else { fprintf(fp, ";W[%c%c]", x, y); } fprintf(fp, "C[%4d %c %2d %2d]\n", i, score[i].color==BLACK?'b':score[i].color==WHITE?'w':'s', score[i].x, score[i].y ); } fprintf(fp, ")\n"); fclose(fp); return 0; } /*--------------------------------------------------------*/ /* 棋譜ファイルの読み込み */ /* */ /* 復帰値 */ /* 0: NO ERROR */ /* 1: fopen() fail */ /* 2: getLine() fail */ /* 3: ungetLine() fail */ /* 4: sscanf() fail (1st) */ /* 5: scoreCount overflow */ /* 6: sscanf() fail (2nd) */ /*--------------------------------------------------------*/ int CMfcKatsunariDoc::loadScore(const char *name ) { FILE *fp; int c, ret, x, y; char key[256], val[256]; if( (fopen_s(&fp,name, "r")) != 0 ){ fprintf(stderr, "ERROR: file(%s) open fail\n", name ); return( 1 ); } initialSetting.boardSize = pureBoardSize/*PURE_BOARD_SIZE*/; initialSetting.handicap = 0; do { c = fgetc(fp); if(c == EOF){ fclose(fp); return( 2 ); } } while(c != '('); for(;;){ ret = _getKeyValue(fp, key, val); if(ret < 0){ fclose(fp); return( 3 ); } else if(ret == 1) break; if( (strcmp(key, "PB") == 0) || (strcmp(key, "PlayerBlack") == 0) ){ if ((initialSetting.blackName = (char *)malloc(strlen(val)+1))!=NULL) { strcpy_s(initialSetting.blackName,sizeof(initialSetting.blackName),val); } if(strcmp(val, "katsunari") == 0){ initialSetting.blackSide = COMPUTER; } else { initialSetting.blackSide = HUMAN; } }else if( (strcmp(key, "PW") == 0) || (strcmp(key, "PlayerWhite") == 0) ){ if ((initialSetting.whiteName = (char *)malloc(strlen(val)+1))!=NULL) { strcpy_s(initialSetting.whiteName,sizeof(initialSetting.whiteName),val); } if(strcmp(val, "katsunari") == 0){ initialSetting.whiteSide = COMPUTER; }else{ initialSetting.whiteSide = HUMAN; } }else if( (strcmp(key, "HA") == 0) ){ initialSetting.handicap = atoi(val); } else if( (strcmp(key, "B") == 0) || (strcmp(key, "W") == 0) || (strcmp(key, "Black") == 0) || (strcmp(key, "White") == 0) ){ break; } } hama[BLACK] = 0; hama[WHITE] = 0; scoreCount = 0; while(ret != 1){ if (scoreCount >= MOVE_COUNT_MAX) { return( 4 ); } if( (strcmp(key, "B") == 0) || (strcmp(key, "Black") == 0) ){ scoreCount++; x = ('a' <= val[0] && val[0] <= 's')? val[0] - 'a' + 1: 0; score[scoreCount].x = x; y = ('a' <= val[1] && val[1] <= 's')? val[1] - 'a' + 1: 0; score[scoreCount].y = y; score[scoreCount].color = BLACK; } else if( (strcmp(key, "W") == 0) || (strcmp(key, "White") == 0) ){ scoreCount++; x = ('a' <= val[0] && val[0] <= 's')? val[0] - 'a' + 1: 0; score[scoreCount].x = x; y = ('a' <= val[1] && val[1] <= 's')? val[1] - 'a' + 1: 0; score[scoreCount].y = y; score[scoreCount].color = WHITE; } ret = _getKeyValue(fp, key, val); if(ret < 0){ fclose(fp); return( 5 ); } } fclose(fp); return( 0 ); } void CMfcKatsunariDoc::recordScore(int x,int y,int colorIn,int moveIn) { scoreCount = moveIn; score[moveIn].x = x; score[moveIn].y = y; score[moveIn].color = colorIn; } void CMfcKatsunariDoc::getScore(int moveIn,int &x,int &y,int &colorIn) { x=score[moveIn].x; y=score[moveIn].y; colorIn=score[moveIn].color; } void CMfcKatsunariDoc::OnUpdateGoKatsunari(CCmdUI* pCmdUI) { pCmdUI->m_bEnableChanged = TRUE; pCmdUI->Enable(Teban==HUMAN); } void CMfcKatsunariDoc::OnGoKatsunari() { GoKatsunari(); } void CMfcKatsunariDoc::OnUpdateNewgame(CCmdUI* pCmdUI) { pCmdUI->m_bEnableChanged = TRUE; pCmdUI->Enable(Initialized); } void CMfcKatsunariDoc::OnUpdateLastvalue(CCmdUI* pCmdUI) { pCmdUI->m_bEnableChanged = TRUE; if (!Initialized) { pCmdUI->Enable(FALSE); } else { pCmdUI->Enable(TRUE); pCmdUI->SetCheck(DispLastValue); } } void CMfcKatsunariDoc::OnLastvalue() { if (DispLastValue) { DispLastValue=0; } else { DispLastValue=1; } UpdateAllViews(NULL); } void CMfcKatsunariDoc::SetTitle(LPCTSTR lpszTitle) { CDocument::SetTitle(lpszTitle); } int CMfcKatsunariDoc::getSpentTime(int colorIn) { return TimeForKatsunari[colorIn] / 1000; } void CMfcKatsunariDoc::ClearGameBoard(int size) { ko_x=ko_y=ko_num=0; ::clearGameBoard(size); // 思考ルーチン側 for(int y=0;ypureBoardSize/*PURE_BOARD_SIZE*/||y>pureBoardSize/*PURE_BOARD_SIZE*/) return 0; int ret=0; if( board[y][x] == colorIn ){ if (x>1) { ret+=DoRemoveRecursive(x-1, y, colorIn,board); } if (y>1) { ret+=DoRemoveRecursive(x, y-1, colorIn,board); } if (xpureBoardSize/*PURE_BOARD_SIZE*/||y>pureBoardSize/*PURE_BOARD_SIZE*/) return TRUE; if (board[y][x]==SPACE) return FALSE; if( board[y][x] == colorIn ){ if (x>1) { if (!CheckRemoveRecursive(x-1, y, colorIn,board )) { return FALSE; } } if (y>1) { if (!CheckRemoveRecursive(x, y-1, colorIn,board )) { return FALSE; } } if (x1 && board[y][x-1]==opp && CheckRemove(x-1,y,opp,board)) ) return FALSE; if ( (y>1 && board[y-1][x]==opp && CheckRemove(x,y-1,opp,board)) ) return FALSE; if ( (x pureBoardSize/*PURE_BOARD_SIZE*/ || x < 0 || y > pureBoardSize/*PURE_BOARD_SIZE*/ || y < 0 ){ return( FALSE ); /* FALSE=0 */ } if( (x == 0) || (y == 0) ){ // パス return( TRUE ); } if (Ban[y][x]!=SPACE) return FALSE; // コウ チェック if (ko_x==x && ko_y==y && ko_num==moveIn-1) return FALSE; if (checkSuicide(x,y,colorIn,board)) return FALSE; return TRUE; } int CMfcKatsunariDoc::SetStoneOnGameBoard(int x,int y,int colorIn,int moveIn) { ::setStoneOnGameBoard(x,y,colorIn,moveIn,pureBoardSize); // 思考部分のもの bool isSingleStone=true; if (Ban[y-1][x]==colorIn || Ban[y+1][x]==colorIn || Ban[y][x+1]==colorIn || Ban[y][x-1]==colorIn) { isSingleStone=false; } int tmpBoard[BOARD_SIZE][BOARD_SIZE]; memcpy(tmpBoard,Ban,sizeof(Ban)); int ret=0; Ban[y][x]=colorIn; int opp=(colorIn==WHITE)?BLACK:WHITE; if (CheckRemove(x+1,y,opp,Ban)) { ret+=DoRemove(x+1,y,opp,Ban); } if (CheckRemove(x-1,y,opp,Ban)) { ret+=DoRemove(x-1,y,opp,Ban); } if (CheckRemove(x,y+1,opp,Ban)) { ret+=DoRemove(x,y+1,opp,Ban); } if (CheckRemove(x,y-1,opp,Ban)) { ret+=DoRemove(x,y-1,opp,Ban); } if (ret==1 && isSingleStone) { ko_num=moveIn; // どこを取った? if (Ban[y][x+1]==SPACE && tmpBoard[y][x+1]!=SPACE) { ko_x=x+1; ko_y=y; } if (Ban[y][x-1]==SPACE && tmpBoard[y][x-1]!=SPACE) { ko_x=x-1; ko_y=y; } if (Ban[y+1][x]==SPACE && tmpBoard[y+1][x]!=SPACE) { ko_x=x; ko_y=y+1; } if (Ban[y-1][x]==SPACE && tmpBoard[y-1][x]!=SPACE) { ko_x=x; ko_y=y-1; } } return ret; } void CMfcKatsunariDoc::OnUpdateSetColor(CCmdUI* pCmdUI) { pCmdUI->m_bEnableChanged = TRUE; pCmdUI->Enable(TRUE); } void CMfcKatsunariDoc::OnSetColor() { // ダイアログを開いて、色を設定しよう。 CColorDialog dlg(RGB(R,G,B),0,AfxGetMainWnd()); if (dlg.DoModal()==IDOK) { int colorWk=dlg.GetColor(); R=colorWk & 0xff; G=(colorWk >> 8) & 0xff; B=(colorWk >>16) & 0xff; UpdateAllViews(NULL); } } void CMfcKatsunariDoc::OnUpdateContinue(CCmdUI* pCmdUI) { pCmdUI->m_bEnableChanged = TRUE; pCmdUI->Enable(Teban==REPLAY); } void CMfcKatsunariDoc::OnContinue() { Teban=BWSide[color]; Play(); } void CMfcKatsunariDoc::OnUpdateStop(CCmdUI* pCmdUI) { pCmdUI->m_bEnableChanged = TRUE; pCmdUI->Enable(Teban!=REPLAY && Teban!=NO_PLAY); } void CMfcKatsunariDoc::OnStop() { Teban=REPLAY; } void CMfcKatsunariDoc::SetLastMoveFromReplay() { if (move>1) { hama[BLACK]=PlayLog[move-1].hama[BLACK]; hama[WHITE]=PlayLog[move-1].hama[WHITE]; // 最後の手の書き換え if (move>2) { LastMove[color]=move-2; LastMoveX[color]=PlayLog[move-2].x; LastMoveY[color]=PlayLog[move-2].y; } else { LastMove[color]=0; LastMoveX[color]=0; LastMoveY[color]=0; } int OppornentColor; if (color==WHITE) { OppornentColor=BLACK; } else { OppornentColor=WHITE; } LastMove[OppornentColor]=move-1; LastX=LastMoveX[OppornentColor]=PlayLog[move-1].x; LastY=LastMoveY[OppornentColor]=PlayLog[move-1].y; } else { hama[BLACK]=0; hama[WHITE]=0; // 最後の手の書き換え LastMove[BLACK]=0; LastMoveX[BLACK]=0; LastMoveY[BLACK]=0; LastMove[WHITE]=0; LastMoveX[WHITE]=0; LastMoveY[WHITE]=0; } } void CMfcKatsunariDoc::OnMatta() { move-=2; replayFromScoreGameBoard(move-1); SetLastMoveFromReplay(); Teban=HUMAN; // HUMANのみUNDO可だから、HUMANの手番に戻る UndoDepth+=2; UpdateAllViews(NULL); } void CMfcKatsunariDoc::OnUpdateMatta(CCmdUI* pCmdUI) { pCmdUI->m_bEnableChanged = TRUE; pCmdUI->Enable(Teban==HUMAN && move>2); }