//////////////////////////////////////////
// MENACEProc.h
// Copyright (c) 12/11/2021 by BCCSkelton
//////////////////////////////////////////

/////////////////////////////////
//主ウィンドウCMyWndの関数の定義
//ウィンドウメッセージ関数
/////////////////////////////////
bool CMyWnd::OnInit(WPARAM wParam, LPARAM lParam) {

	//コモンコントロールの初期化
	InitCommonControls();

	//ツールバー登録−SetHandle(hWnd))
	TBar.SetHandle(GetDlgItem(m_hWnd, IDC_TOOLBAR));
	//ツールバーボタン用カスタムビットマップ追加
	TBar.AddBmp(m_hInstance, MAKEINTRESOURCE(IDI_TOOLBAR), 8);
	//ツールバーボタン追加
	TBBUTTON tbb[11];
	ZeroMemory(tbb, sizeof(tbb));
	tbb[0].iBitmap = TBar.m_id + 0;
	tbb[0].fsState = TBSTATE_ENABLED;
	tbb[0].fsStyle = TBSTYLE_BUTTON;
	tbb[0].idCommand = IDM_OPEN;
	tbb[1].iBitmap = TBar.m_id + 1;
	tbb[1].fsState = TBSTATE_ENABLED;
	tbb[1].fsStyle = TBSTYLE_BUTTON;
	tbb[1].idCommand = IDM_SAVEAS;
	tbb[2].fsStyle = TBSTYLE_SEP;	//セパレーター
	tbb[3].iBitmap = TBar.m_id + 2;
	tbb[3].fsState = TBSTATE_ENABLED;
	tbb[3].fsStyle = TBSTYLE_BUTTON;
	tbb[3].idCommand = IDM_EXIT;
	tbb[4].fsStyle = TBSTYLE_SEP;	//セパレーター
	tbb[5].iBitmap = TBar.m_id + 3;
	tbb[5].fsState = TBSTATE_ENABLED;
	tbb[5].fsStyle = TBSTYLE_BUTTON;
	tbb[5].idCommand = IDM_FM;
	tbb[6].iBitmap = TBar.m_id + 4;
	tbb[6].fsState = TBSTATE_ENABLED;
	tbb[6].fsStyle = TBSTYLE_BUTTON;
	tbb[6].idCommand = IDM_SM;
	tbb[7].iBitmap = TBar.m_id + 5;
	tbb[7].fsState = TBSTATE_ENABLED;
	tbb[7].fsStyle = TBSTYLE_BUTTON;
	tbb[7].idCommand = IDM_AUTO;
	tbb[8].fsStyle = TBSTYLE_SEP;	//セパレーター
	tbb[9].iBitmap = TBar.m_id + 6;
	tbb[9].fsState = TBSTATE_ENABLED;
	tbb[9].fsStyle = TBSTYLE_BUTTON;
	tbb[9].idCommand = IDM_ABOUT;
	tbb[10].iBitmap = TBar.m_id + 7;
	tbb[10].fsState = TBSTATE_ENABLED;
	tbb[10].fsStyle = TBSTYLE_BUTTON;
	tbb[10].idCommand = IDM_VERSION;
	TBar.AddButtons(11, tbb);

	//ステータスバー登録−SetHandle(hWnd))
	SBar.SetHandle(GetDlgItem(m_hWnd, IDC_STATUSBAR));
	//ステータスバー区画設定
	int sec[2] = {90, -1};
	SBar.SetSection(2, sec);
	//ステータスバー文字列設定
	SBar.SetText(0, "MENACE Ver 1.0");
	//ボタンに張り付け用ビットマップの読み込み
	g_hNought = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDI_NOUGHT), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE);
	g_hCross = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDI_CROSS), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE);
	g_hVacant = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDI_VACANT), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE);
	//メンバー変数の初期化
	m_Games = 0;		//連続機械対戦のゲーム数
	m_1st = 0;			//先手の勝数
	m_2nd = 0;			//後手の勝数
	m_Draw = 0;			//引き分け数
	//データファイル名の設定と読み込み
	m_FileName = arg.Path();
	m_FileName = m_FileName + "\\MENACE.dat";
	m_Menace.BoardRead(m_FileName.ToChar());
	//メニュー、メニューボタンを有効化し、〇×ボタンを無効化する
	ChangeMenuStatus(TRUE);

	return TRUE;
}

bool CMyWnd::OnNotify(WPARAM wParam, LPARAM lParam) {

	//ツールバーからのツールチップ情報取得
	switch (((LPNMHDR)lParam)->code) {
		case TTN_NEEDTEXT:
			static LPTOOLTIPTEXT lptip;
			lptip = (LPTOOLTIPTEXT)lParam;
			switch (lptip->hdr.idFrom) {
				case IDM_OPEN:
					lptip->lpszText = "データを開く";
					break;
				case IDM_SAVEAS:
					lptip->lpszText = "データコピーを保存";
					break;
				case IDM_EXIT:
					lptip->lpszText = "終了";
					break;
				case IDM_FM:
					lptip->lpszText = "先手";
					break;
				case IDM_SM:
					lptip->lpszText = "後手";
					break;
				case IDM_AUTO:
					lptip->lpszText = "自動対局";
					break;
				case IDM_ABOUT:
					lptip->lpszText = "MENACEについて";
					break;
				case IDM_VERSION:
					lptip->lpszText = "バージョン情報";
					break;
			}
	}
	return TRUE;
}

bool CMyWnd::OnClose(WPARAM wParam, LPARAM lParam) {

	if(MessageBox(m_hWnd, "終了しますか", "終了確認",
	MB_YESNO | MB_ICONINFORMATION) == IDYES) {
		//データを保存
		m_Menace.BoardWrite(m_FileName.ToChar());
		//ビットマップの解放
		DeleteObject((HGDIOBJ)g_hNought);
		DeleteObject((HGDIOBJ)g_hCross);
		DeleteObject((HGDIOBJ)g_hVacant);
		//処理をするとDestroyWindow、PostQuitMessageが呼ばれる
		return TRUE;
	}
	else
		//そうでなければウィンドウではDefWindowProc関数をreturn、ダイアログではreturn FALSEとなる。
		return FALSE;
}

//ダイアログベースの場合はこれが必要
bool CMyWnd::OnDestroy(WPARAM wPram, LPARAM lParam) {

	PostQuitMessage(0);
	return TRUE;
}

/////////////////////////////////
//主ウィンドウCMyWndの関数の定義
//メニュー項目、コントロール関数
/////////////////////////////////
bool CMyWnd::On0() {

	if(m_You == FIRST)
		SendItemMsg(IDC_0, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hNought);
	else if(m_You == SECOND)
		SendItemMsg(IDC_0, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hCross);
	Turn(0);
	return TRUE;
}

bool CMyWnd::On1() {

	if(m_You == FIRST)
		SendItemMsg(IDC_1, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hNought);
	else if(m_You == SECOND)
		SendItemMsg(IDC_1, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hCross);
	Turn(1);
	return TRUE;
}

bool CMyWnd::On2() {

	if(m_You == FIRST)
		SendItemMsg(IDC_2, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hNought);
	else if(m_You == SECOND)
		SendItemMsg(IDC_2, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hCross);
	Turn(2);
	return TRUE;
}

bool CMyWnd::On3() {

	if(m_You == FIRST)
		SendItemMsg(IDC_3, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hNought);
	else if(m_You == SECOND)
		SendItemMsg(IDC_3, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hCross);
	Turn(3);
	return TRUE;
}

bool CMyWnd::On4() {

	if(m_You == FIRST)
		SendItemMsg(IDC_4, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hNought);
	else if(m_You == SECOND)
		SendItemMsg(IDC_4, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hCross);
	Turn(4);
	return TRUE;
}

bool CMyWnd::On5() {

	if(m_You == FIRST)
		SendItemMsg(IDC_5, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hNought);
	else if(m_You == SECOND)
		SendItemMsg(IDC_5, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hCross);
	Turn(5);
	return TRUE;
}

bool CMyWnd::On6() {

	if(m_You == FIRST)
		SendItemMsg(IDC_6, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hNought);
	else if(m_You == SECOND)
		SendItemMsg(IDC_6, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hCross);
	Turn(6);
	return TRUE;
}

bool CMyWnd::On7() {

	if(m_You == FIRST)
		SendItemMsg(IDC_7, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hNought);
	else if(m_You == SECOND)
		SendItemMsg(IDC_7, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hCross);
	Turn(7);
	return TRUE;
}

bool CMyWnd::On8() {

	if(m_You == FIRST)
		SendItemMsg(IDC_8, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hNought);
	else if(m_You == SECOND)
		SendItemMsg(IDC_8, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hCross);
	Turn(8);
	return TRUE;
}

bool CMyWnd::OnOpen() {

	char* fn = cmndlg.GetFileName(m_hWnd, "DATファイル(*.dat)\0*.dat\0\0", TRUE, "dat", ".", "MENACEデータファイルを開く");
	if(!fn) {
		MessageBox(m_hWnd, "処理がキャンセルされました", "エラー", MB_OK | MB_ICONERROR);
		return FALSE;
	}
	else
		m_Menace.BoardRead(fn);
	return TRUE;
}

bool CMyWnd::OnSave() {

	//データを保存
	m_Menace.BoardWrite(m_FileName.ToChar());
	return TRUE;
}

bool CMyWnd::OnSaveas() {

	char* fn = cmndlg.GetFileName(m_hWnd, "DATファイル(*.dat)\0*.dat\0\0", FALSE, "dat", ".", "MENACEデータファイル（コピー）の保存");
	if(!fn) {
		MessageBox(m_hWnd, "処理がキャンセルされました", "エラー", MB_OK | MB_ICONERROR);
		return FALSE;
	}
	else {
		//データを保存
		m_Menace.BoardWrite(fn);
	}
	return TRUE;
}

bool CMyWnd::OnExit() {

	SendMsg(WM_CLOSE, 0, 0);
	return TRUE;
}

bool CMyWnd::OnFm() {

	m_You = FIRST;
	Init();
	ChangeMenuStatus(FALSE);
	return TRUE;
}

bool CMyWnd::OnSm() {

	m_You = SECOND;
	Init();
	ChangeMenuStatus(FALSE);
	Turn(0);
	return TRUE;
}

bool CMyWnd::OnAuto() {

	m_You = 3;
	int n = inputdlg.DoModal(m_hWnd, "IDD_INPUT", inputdlgProc);
	for(int i = 0; i < n; i++) {	//100、500、1000、10000連戦
		Init();
		ChangeMenuStatus(FALSE);
		while(!Turn(0));			//機械対戦に引数は関係ない
	}
	return TRUE;
}

bool CMyWnd::OnAbout() {

	infodlg.DoModal(m_hWnd, "IDD_INFO", infodlgProc);
	return TRUE;
}

bool CMyWnd::OnVersion() {

	versiondlg.DoModal(m_hWnd, "IDD_VERSION", versiondlgProc);
	return TRUE;
}

///////////////////
//ユーザー定義関数
///////////////////
//ゲーム初期化関数
void CMyWnd::Init() {

	m_Menace.Init();
	m_Result = 0;		//ゲーム結果（未了0、先手勝利1、後手勝利2、引き分け3）
	m_Times = 0;		//各対戦の手数カウンター
	for(int i = 0; i < 9; i++)
		SendItemMsg(IDC_0 + i, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hVacant);

}

//ゲーム処理関数
int CMyWnd::Turn(int pos) {

	for(int i = 0; !m_Result && i < 2; i++) {	//対戦未了なら先手、後手が一回づつ手を打つ
		switch(m_You) {
		case FIRST:		//Playerが先手
			if(!(m_Times % 2))		//先手番
				m_Menace.MakeMove(pos, FIRST);
			else {					//後手番
				if(!m_Menace.AutoMove(SECOND)) {	//打つ手がない場合
					m_Result = m_Menace.WhoWon();	//先手の勝利
				}
				else {
					//AutoMoveの際の〇×の表示
					int move = m_Menace.GetLastMove();	//m_Board.m_LastMoveの最後の手の位置を取得
					SendItemMsg(IDC_0 + move, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hCross);
				}
			}
			break;
		case SECOND:	//Playerが後手
			if(m_Times % 2) {		//先手番
				if(!m_Menace.AutoMove(FIRST)) {		//打つ手がない場合
					m_Result = m_Menace.WhoWon();	//相手の勝利
				}
				else {
					//AutoMoveの際の〇×の表示
					int move = m_Menace.GetLastMove();	//m_Board.m_LastMoveの最後の手の位置を取得
					SendItemMsg(IDC_0 + move, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hNought);
				}
			}
			else					//後手番
				m_Menace.MakeMove(pos, SECOND);
			break;
		case 3:			//機械対戦
			if(!(m_Times % 2)) {	//先手番
				if(!m_Menace.AutoMove(FIRST)) {		//打つ手がない場合
					m_Result = m_Menace.WhoWon();	//相手の勝利
				}
				else {
					int move = m_Menace.GetLastMove();	//m_Board.m_LastMoveの最後の手の位置を取得
					SendItemMsg(IDC_0 + move, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hNought);
				}
			}
			else {					//後手番
				if(!m_Menace.AutoMove(SECOND)) {	//打つ手がない場合
					m_Result = m_Menace.WhoWon();	//相手の勝利
				}
				else {
					int move = m_Menace.GetLastMove();	//m_Board.m_LastMoveの最後の手の位置を取得
					SendItemMsg(IDC_0 + move, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)g_hCross);
				}
			}
			break;
		}
		m_Times++;
		//第5手目（プログラム上はゼロベースなので4手目）以降勝敗が付いていないならば
		if(!m_Result && m_Times > 4)
			m_Result = m_Menace.IsOver();
	}
	if(m_Result)
		WhenOver();		//ゲーム終了処理
	return m_Result;	//ゲーム結果を返す
}

void CMyWnd::WhenOver() {
	
	m_Games++;
	switch(m_Result) {	//先手勝利(-1)、後手勝利(2)、先手敗北(-1)、後手敗北(-2)
	case FIRST:
		SBar.SetText(1, "先手の勝ち");
		SBar.SendMsg(SB_SETTIPTEXT, 1, (LPARAM)"先手の勝ち");	//ToolTipをつける
		m_1st++;
		m_Menace.Register();		//終了時盤面の記録
		m_Menace.PushBack();		//一手前の相手の盤面（敗北因）に戻す
		m_Menace.Register();		//敗北盤面の記録
		break;
	case SECOND:
		SBar.SetText(1, "後手の勝ち");
		SBar.SendMsg(SB_SETTIPTEXT, 1, (LPARAM)"後手の勝ち");	//ToolTipをつける
		m_2nd++;
		m_Menace.Register();		//終了時盤面の記録
		m_Menace.PushBack();		//一手前の相手の盤面（敗北因）に戻す
		m_Menace.Register();		//敗北盤面の記録
		break;
	case 3:
		SBar.SetText(1, "引き分け");
		SBar.SendMsg(SB_SETTIPTEXT, 1, (LPARAM)"引き分け");	//ToolTipをつける
		m_Draw++;
		break;
	case -1:
		SBar.SetText(1, "先手の負け");
		SBar.SendMsg(SB_SETTIPTEXT, 1, (LPARAM)"先手の負け");	//ToolTipをつける
		m_2nd++;
		m_Menace.Register();		//終了時一手前、投了時盤面の記録
		break;
	case -2:
		SBar.SetText(1, "後手の負け");
		SBar.SendMsg(SB_SETTIPTEXT, 1, (LPARAM)"後手の負け");	//ToolTipをつける
		m_1st++;
		m_Menace.Register();		//終了時一手前、投了時盤面の記録
		break;
	}
	ChangeMenuStatus(TRUE);			//ゲームメニューと先手、後手、機械対戦のボタンを有効化する
}

void CMyWnd::ChangeMenuStatus(bool EnableFlag) {

	HMENU hMenu = GetMenu(MENACE.GetHandle());	//メニューハンドルの取得
	//メニューバー
	EnableMenuItem(hMenu, 1, MF_BYPOSITION | (EnableFlag ? MF_ENABLED : MF_GRAYED));
	DrawMenuBar(MENACE.GetHandle());	//Re-draw
	//ツールバー(MAKELONGマクロは16bit整数2つをunsigned 32bit整数にする)
	SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_FM, MAKELONG(EnableFlag, 0));
	SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_SM, MAKELONG(EnableFlag, 0));
	SendMessage(TBar.GetHandle(), TB_ENABLEBUTTON, IDM_AUTO, MAKELONG(EnableFlag, 0));
	//〇×ボタンの有効、無効化
	for(int i = 0; i < 9; i++)
		EnableWindow(GetDlgItem(m_hWnd, IDC_0 + i), (EnableFlag ? FALSE : TRUE));
}

///////////////////////////////
//ユーザーダイアログの関数定義
//Inputダイアログ
///////////////////////////////
bool INPUTDLG::OnInit(WPARAM wParam, LPARAM lParam) {

	SendItemMsg(IDC_GAMES, CB_INSERTSTRING, 0, (LPARAM)"100");
	SendItemMsg(IDC_GAMES, CB_INSERTSTRING, 1, (LPARAM)"500");
	SendItemMsg(IDC_GAMES, CB_INSERTSTRING, 2, (LPARAM)"1000");
	return TRUE;
}

bool INPUTDLG::OnOk() {

	int n = SendItemMsg(IDC_GAMES, CB_GETCURSEL, 0, 0);
	if(n == CB_ERR) {
		MessageBox(m_hWnd, "回数が選択されていません", "エラー", MB_OK | MB_ICONERROR);
		return FALSE;
	}
	switch(n) {
	case 0:
		n = 100;
		break;
	case 1:
		n = 500;
		break;
	case 2:
		n = 1000;
		break;
	}
	EndModal(n);
	return TRUE;
}

bool INPUTDLG::OnCancel() {

	EndModal(FALSE);
	return TRUE;
}

///////////////////////////////
//ユーザーダイアログの関数定義
//Infoダイアログ
///////////////////////////////
bool INFODLG::OnInit(WPARAM wParam, LPARAM lParam) {

	//MENACEについての情報開示
	CSTR num(MENACE.m_Menace.DBSize());
	SendItemMsg(IDC_EDIT1, WM_SETTEXT, 0, (LPARAM)num.ToChar());
	num = MENACE.m_Games;
	SendItemMsg(IDC_EDIT2, WM_SETTEXT, 0, (LPARAM)num.ToChar());
	num = MENACE.m_1st;
	SendItemMsg(IDC_EDIT3, WM_SETTEXT, 0, (LPARAM)num.ToChar());
	num = MENACE.m_2nd;
	SendItemMsg(IDC_EDIT4, WM_SETTEXT, 0, (LPARAM)num.ToChar());
	num = MENACE.m_Draw;
	SendItemMsg(IDC_EDIT5, WM_SETTEXT, 0, (LPARAM)num.ToChar());
	return TRUE;
}

bool INFODLG::OnOk() {

	EndModal(TRUE);
	return TRUE;
}

bool INFODLG::OnCancel() {

	EndModal(FALSE);
	return TRUE;
}

///////////////////////////////
//ユーザーダイアログの関数定義
//Versionダイアログ
///////////////////////////////
bool VERSIONDLG::OnOk() {

	EndModal(TRUE);
	return TRUE;
}

bool VERSIONDLG::OnCancel() {

	EndModal(FALSE);
	return TRUE;
}
