#include #include #include #include #include #include "watzee.h" static char *AppName = "Watzee"; static char ClassName[32]="Watzee"; static void DoScore( HDC, WORD ); static void DoScoreTotals( HDC ); static WORD GetDieCheck( HWND, POINT ); static WORD GetScoreCheck( POINT ); static void InitializeGameData( void ); static void NextPlayer( HWND, HDC ); long _EXPORT FAR PASCAL WndProc( HWND, UINT, WPARAM, LPARAM ); /* * WinMain -- register the window class and call some initialization * routines; then send a message to WndProc to start a new * game */ int PASCAL WinMain( HINSTANCE instance, HINSTANCE previnstance, LPSTR cmdline, int cmdshow ) /*******************************************************/ { HWND hwnd; MSG msg; WNDCLASS wndclass; cmdline = cmdline; previnstance = previnstance; #ifdef __WINDOWS_386__ sprintf( ClassName,"Watzee%d",instance ); #else if( !previnstance ) { #endif wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = (LPVOID) WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 6 * sizeof( DWORD ); wndclass.hInstance = instance; wndclass.hIcon = LoadIcon( instance, AppName ); wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); wndclass.hbrBackground = GetStockObject( WHITE_BRUSH ); wndclass.lpszMenuName = AppName; wndclass.lpszClassName = ClassName; RegisterClass( &wndclass ); #ifndef __WINDOWS_386__ } #endif InitializeGameData(); GetFontInfo(); CreateFonts(); hwnd = CreateWindow( ClassName, "WATZEE", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CharWidth * 28 + CharWidth / 2, CharHeight * 28, NULL, NULL, instance, NULL ); GetDiceBitmaps( hwnd ); ShowWindow( hwnd, cmdshow ); UpdateWindow( hwnd ); SendMessage( hwnd, WMW_START_NEW_GAME, 0, 0 ); while( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } return( msg.wParam ); } /* * WndProc -- process messages from Windows */ long _EXPORT FAR PASCAL WndProc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam ) /*********************************************************************/ { static HANDLE hdlginstance; static BOOL got_watzee_bonus; PAINTSTRUCT ps; FARPROC dlg_proc; HDC hdc; POINT point; short x; short y; short dy; short i; switch( message ) { case WM_CREATE : hdlginstance = ((CREATESTRUCT far *) MK_FP32((void*)lparam))->hInstance; x = CharWidth * 22 + CharWidth / 2; y = CharHeight * 3; dy = CharHeight * 3; dy += dy / 7; /* create the check marks for the dice bitmaps, and the ROLL and OK buttons */ for( i = 0; i < 5; i++, y += dy ) { CreateWindow( "BUTTON", "", WS_CHILD|WS_VISIBLE|BS_CHECKBOX, x, y, CharWidth, CharHeight, hwnd, (HMENU)(IDW_DICE1+i), hdlginstance, NULL ); } CreateWindow( "BUTTON", "ROLL", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, x, CharHeight * 19, 9 * CharWidth / 2 , CharHeight * 2, hwnd, (HMENU)IDW_ROLL, hdlginstance, NULL ); CreateWindow( "BUTTON", "OK", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, x, 43 * CharHeight / 2, 9 * CharWidth / 2, CharHeight * 2, hwnd, (HMENU)IDW_OK, hdlginstance, NULL ); return( 0 ); case WMW_START_NEW_GAME : dlg_proc = MakeProcInstance( (FARPROC)GetNumPlayersDialogProc, hdlginstance ); DialogBox( hdlginstance, "GetNumPlayers", hwnd, (DLGPROC)dlg_proc ); FreeProcInstance( dlg_proc ); dlg_proc = MakeProcInstance( (FARPROC)GetInitialsDialogProc, hdlginstance ); DialogBox( hdlginstance, "GetPlayersInitials", hwnd, (DLGPROC)dlg_proc ); FreeProcInstance( dlg_proc ); EnableWindow( GetDlgItem( hwnd, IDW_OK ), FALSE ); EnableWindow( GetDlgItem( hwnd, IDW_ROLL ), TRUE ); PlayingGameYet = TRUE; InvalidateRect( hwnd, NULL, FALSE ); for( i = 0; i < NumberOfPlayers; i++ ) { if( Player[i][IS_COMPUTER] ) break; } if( i < NumberOfPlayers && !GotTimer ) { while( !SetTimer( hwnd, ID_TIMER, TIMER_INTERVAL, NULL ) ) { if( MessageBox( hwnd, "Too many clocks or timers are active", AppName, MB_ICONEXCLAMATION|MB_RETRYCANCEL ) == IDCANCEL ) { DestroyWindow( hwnd ); return( 0 ); } } GotTimer = TRUE; } if( i == 0 ) { PCTurn = TRUE; EnableWindow( GetDlgItem( hwnd, IDW_ROLL ), FALSE ); } hdc = GetDC( hwnd ); RollDice( hwnd, hdc ); GetDiceInfo(); ReleaseDC( hwnd, hdc ); // SetFocus( hwnd ); return( 0 ); case WM_COMMAND : switch( LOWORD( wparam ) ) { case IDM_NEWGAME : if( GotTimer ) { KillTimer( hwnd, ID_TIMER ); } if( MessageBox( hwnd, "Start New Game: Are you sure?", "WATZEE", MB_YESNO | MB_ICONEXCLAMATION ) == IDYES ) { InitializeGameData(); InvalidateRect( hwnd, NULL, TRUE ); SendMessage( hwnd, WMW_START_NEW_GAME, 0, 0 ); } else if( GotTimer ) { SetTimer( hwnd, ID_TIMER, TIMER_INTERVAL, NULL ); } break; case IDM_OPTIONS : if( GotTimer ) { KillTimer( hwnd, ID_TIMER ); } dlg_proc = MakeProcInstance( (FARPROC)OptionsDialogProc, hdlginstance ); DialogBox( hdlginstance, "Options", hwnd, (DLGPROC)dlg_proc ); FreeProcInstance( dlg_proc ); if( GotTimer ) { SetTimer( hwnd, ID_TIMER, TIMER_INTERVAL, NULL ); } break; case IDM_EXIT : DestroyWindow( hwnd ); break; case IDM_SCORING : if( GotTimer ) { KillTimer( hwnd, ID_TIMER ); } dlg_proc = MakeProcInstance( (FARPROC)HelpDialogProc, hdlginstance ); DialogBox( hdlginstance, "WatzeeHelp", hwnd, (DLGPROC)dlg_proc ); FreeProcInstance( dlg_proc ); if( GotTimer ) { SetTimer( hwnd, ID_TIMER, TIMER_INTERVAL, NULL ); } break; case IDM_ABOUT : if( GotTimer ) { KillTimer( hwnd, ID_TIMER ); } dlg_proc = MakeProcInstance( (FARPROC)AboutDialogProc, hdlginstance ); DialogBox( hdlginstance, "AboutWatzee", hwnd, (DLGPROC)dlg_proc ); FreeProcInstance( dlg_proc ); if( GotTimer ) { SetTimer( hwnd, ID_TIMER, TIMER_INTERVAL, NULL ); } break; case IDW_DICE1 : case IDW_DICE2 : case IDW_DICE3 : case IDW_DICE4 : case IDW_DICE5 : if( !PCTurn && CurrentRoll < 2 ) { SendMessage( hwnd, WMW_DIE_CHECK, wparam, 0 ); } break; case IDW_ROLL : SendMessage( hwnd, WMW_ROLL, 0, 0 ); break; case IDW_OK : SendMessage( hwnd, WMW_OK, 0, 0 ); break; } return( 0 ); case WM_LBUTTONUP : if( !PCTurn ) { MAKE_POINT( point, lparam ); if( point.x > CharWidth * 24 && point.y < CharHeight * 20 ) { wparam = GetDieCheck( hwnd, point ); if( wparam && CurrentRoll < 2 ) { SendMessage( hwnd, WMW_DIE_CHECK, wparam, 0 ); } } else { wparam = GetScoreCheck( point ); if( wparam && Player[CurrentPlayer][wparam] == UNDEFINED ) { SendMessage( hwnd, WMW_SCORE_CHECK, wparam, 0 ); } } } return( 0 ); case WMW_DIE_CHECK : i = LOWORD( wparam ) - IDW_DICE1; Dice[i].is_checked = !Dice[i].is_checked; CheckDlgButton( hwnd, wparam, (BOOL)Dice[i].is_checked ); // SetFocus( hwnd ); return( 0 ); case WMW_SCORE_CHECK : hdc = GetDC( hwnd ); if( wparam != LastScoreSelection ) { DoScore( hdc, wparam ); EnableWindow( GetDlgItem( hwnd, IDW_OK ), TRUE ); } ReleaseDC( hwnd, hdc ); // SetFocus( hwnd ); return( 0 ); case WMW_ROLL : hdc = GetDC( hwnd ); if( DieCheckMeansRoll ) { for( i = 0; i < 5; i++ ) { if( Dice[i].is_checked ) break; } } else { for( i = 0; i < 5; i++ ) { if( !Dice[i].is_checked ) break; } } if( i < 5 ) { if( LastScoreSelection ) { Player[CurrentPlayer][LastScoreSelection] = UNDEFINED; WriteScore( hdc, CurrentPlayer, LastScoreSelection ); DoScoreTotals( hdc ); LastScoreSelection = 0; } got_watzee_bonus = FALSE; CurrentRoll++; RollDice( hwnd, hdc ); GetDiceInfo(); if( DiceInfo.got_watzee && Player[CurrentPlayer][WATZEE] == 50 ) { got_watzee_bonus = TRUE; } if( CurrentRoll == 2 ) { EnableWindow( GetDlgItem( hwnd, IDW_ROLL ), FALSE ); } } ReleaseDC( hwnd, hdc ); // SetFocus( hwnd ); return( 0 ); case WMW_OK : hdc = GetDC( hwnd ); LastScoreSelection = 0; if( got_watzee_bonus ) { DoScore( hdc, WATZEE_BONUS ); LastScoreSelection = 0; got_watzee_bonus = FALSE; } NextPlayer( hwnd, hdc ); ReleaseDC( hwnd, hdc ); // SetFocus( hwnd ); return( 0 ); case WMW_GAME_OVER : hdc = GetDC( hwnd ); WriteScoreOptions( hdc ); ReleaseDC( hwnd, hdc ); if( GotTimer ) { KillTimer( hwnd, ID_TIMER ); GotTimer = FALSE; } if( MessageBox( hwnd, "Another Game ?", "WATZEE", MB_YESNO ) == IDYES ) { InitializeGameData(); InvalidateRect( hwnd, NULL, TRUE ); SendMessage( hwnd, WMW_START_NEW_GAME, 0, 0 ); } else { DestroyWindow( hwnd ); } return( 0 ); case WM_TIMER : if( PCTurn ) { PCPlay( hwnd ); } return( 0 ); case WM_PAINT : hdc = BeginPaint( hwnd, &ps ); DrawDice( hwnd, hdc ); DrawScoreCard( hdc ); WriteScoreOptions( hdc ); if( PlayingGameYet ) { WriteInitials( hdc ); HighliteName( hdc, CurrentPlayer ); WriteScores( hdc ); } EndPaint( hwnd, &ps ); return( 0 ); case WM_DESTROY : { HBITMAP hbm; if( GotTimer ) { KillTimer( hwnd, ID_TIMER ); } for( i = 0; i < 6; i++ ) { hbm = (HBITMAP)GetWindowLong( hwnd, i * sizeof( DWORD ) ); DeleteObject( hbm ); } PostQuitMessage( 0 ); return( 0 ); } } return( DefWindowProc( hwnd, message, wparam, lparam ) ); } /* * DoScore -- update the score card after a score selection */ static void DoScore( HDC hdc, WORD selection ) /********************************************/ { HFONT hfont; short score; score = 0; if( LastScoreSelection ) { Player[CurrentPlayer][LastScoreSelection] = UNDEFINED; WriteScore( hdc, CurrentPlayer, LastScoreSelection ); DoScoreTotals( hdc ); } LastScoreSelection = selection; switch( selection ) { case ACES : case TWOS : case THREES : case FOURS : case FIVES : case SIXES : score = DiceInfo.count[selection] * selection; break; case THREE_KIND : if( DiceInfo.got_three_kind ) { score = DiceInfo.sum; } break; case FOUR_KIND : if( DiceInfo.got_four_kind ) { score = DiceInfo.sum; } break; case FULL_HOUSE : if( DiceInfo.got_full_house ) { score = 25; } break; case SMALL_STRAIGHT : if( DiceInfo.got_small_straight ) { score = 30; } break; case LARGE_STRAIGHT : if( DiceInfo.got_large_straight ) { score = 40; } break; case WATZEE : if( DiceInfo.got_watzee ) { score = 50; } break; case WATZEE_BONUS : score = Player[CurrentPlayer][WATZEE_BONUS]; if( score == UNDEFINED ) { score = 100; } else { score += 100; } break; case CHANCE : score = DiceInfo.sum; break; } Player[CurrentPlayer][selection] = score; hfont = SelectObject( hdc, CreateFontIndirect( &SmallBoldFont ) ); WriteScore( hdc, CurrentPlayer, selection ); DeleteObject( SelectObject( hdc, hfont ) ); DoScoreTotals( hdc ); } /* * DoScoreTotals -- update the current player's Upper Total, Bonus, Lower Total * and Grand Total */ static void DoScoreTotals( HDC hdc ) /**********************************/ { short upper_total; short lower_total; short i; upper_total = 0; lower_total = 0; for( i = ACES; i <= SIXES; i++ ) { if( Player[CurrentPlayer][i] != UNDEFINED ) { upper_total += Player[CurrentPlayer][i]; } } if( upper_total >= 63 ) { upper_total += 35; Player[CurrentPlayer][BONUS] = 35; } Player[CurrentPlayer][UPPER_TOTAL] = upper_total; for( i = THREE_KIND; i <= WATZEE_BONUS; i++ ) { if( Player[CurrentPlayer][i] != UNDEFINED ) { lower_total += Player[CurrentPlayer][i]; } } Player[CurrentPlayer][LOWER_TOTAL] = lower_total; Player[CurrentPlayer][GRAND_TOTAL] = upper_total + lower_total; SelectObject( hdc, GetStockObject( SYSTEM_FONT ) ); for( i = BONUS; i <= GRAND_TOTAL; i++ ) { WriteScore( hdc, CurrentPlayer, i ); } } /* * GetDieCheck -- determine where on the score card the user just clicked, * and decide whether the user just checked one of the die; * return a value between 1 and 5 indicating which die, or * zero if a die was not clicked */ static WORD GetDieCheck( HWND hwnd, POINT point ) /***********************************************/ { BITMAP bm; RECT rect; WORD die_checked; short dy; short i; HBITMAP hbm; die_checked = 0; hbm = (HBITMAP)GetWindowLong( hwnd, 0 ); GetObject( hbm, sizeof( BITMAP ), (LPSTR) &bm ); rect.top = CharHeight * 2; rect.bottom = rect.top + bm.bmHeight; rect.left = CharWidth * 24; rect.right = rect.left + bm.bmWidth; dy = bm.bmHeight + bm.bmHeight / 7; for( i = 0; i < 5; i++ ) { if( PtInRect( &rect, point ) ) break; rect.top += dy; rect.bottom += dy; } if( i < 5 ) { die_checked = IDW_DICE1 + i; } return( die_checked ); } /* * GetScoreCheck -- determine where on the score card the user just clicked, * and decide whether the user just made a valid score * selection; return the score option that was chosen, or * zero if a score option was not clicked */ static WORD GetScoreCheck( POINT point ) /**************************************/ { short x; short y; short char_height; short char_width; short score_option_vline; short left_column; short right_column; short score_selection; x = point.x; y = point.y; score_selection = 0; char_height = CharHeight; char_width = CharWidth; score_option_vline = char_width * SCORE_OPTIONS_WIDTH + char_width; left_column = score_option_vline + CurrentPlayer * char_width * 3; right_column = left_column + char_width * 3; if( ( x < score_option_vline && x > char_width ) || ( x > left_column && x < right_column ) ) { if( y < char_height * 9 && y > char_height * 3 ) { if( y < char_height * 6 ) { if( y < char_height * 4 ) { score_selection = ACES; } else if( y < char_height * 5 ) { score_selection = TWOS; } else { score_selection = THREES; } } else { if( y < char_height * 7 ) { score_selection = FOURS; } else if( y < char_height * 8 ) { score_selection = FIVES; } else { score_selection = SIXES; } } } else if( y > char_height * 12 && y < char_height * 19 ) { if( y < char_height * 16 ) { if( y < char_height * 14 ) { if( y < char_height * 13 ) { score_selection = THREE_KIND; } else { score_selection = FOUR_KIND; } } else if( y < char_height * 15 ) { score_selection = FULL_HOUSE; } else { score_selection = SMALL_STRAIGHT; } } else if( y < char_height * 17 ) { score_selection = LARGE_STRAIGHT; } else if( y < char_height * 18 ) { score_selection = WATZEE; } else { score_selection = CHANCE; } } } return( score_selection ); } /* * InitializeGameData -- initialize the scores, the player's initials, and * other global variables */ static void InitializeGameData( void ) /************************************/ { short i; short j; NumberOfPlayers = 0; PlayingGameYet = FALSE; CurrentTurn = 0; CurrentPlayer = 0; CurrentRoll = 0; DieCheckMeansRoll = TRUE; ResetDieChecks = TRUE; GotTimer = FALSE; LastScoreSelection = 0; PCTurn = FALSE; for( i = 0; i < MAX_PLAYERS; i++ ) { Player[i][IS_COMPUTER] = FALSE; for( j = ACES; j < LOWER_TOTAL; j++ ) { Player[i][j] = UNDEFINED; } Player[i][UPPER_TOTAL] = 0; Player[i][LOWER_TOTAL] = 0; Player[i][GRAND_TOTAL] = 0; sprintf( PlayerName[i], " " ); } for( i = 0; i < 5; i++ ) { Dice[i].value = i+1; Dice[i].is_checked = TRUE; } } /* * NextPlayer -- determine if the game is over; if not, reset the * CurrentTurn counter for the next player and initialize * the dice */ static void NextPlayer( HWND hwnd, HDC hdc ) /******************************************/ { BOOL reset_value; short i; PCTurn = FALSE; HighliteName( hdc, CurrentPlayer ); CurrentPlayer++; if( CurrentPlayer == NumberOfPlayers ) { CurrentPlayer = 0; CurrentTurn++; if( CurrentTurn == 13 ) { SendMessage( hwnd, WMW_GAME_OVER, 0, 0 ); return; } } HighliteName( hdc, CurrentPlayer ); WriteScoreOptions( hdc ); CurrentRoll = 0; reset_value = FALSE; if( DieCheckMeansRoll ) { reset_value = TRUE; } for( i = 0; i < 5; i++ ) { Dice[i].is_checked = reset_value; CheckDlgButton( hwnd, IDW_DICE1+i, reset_value ); } RollDice( hwnd, hdc ); GetDiceInfo(); EnableWindow( GetDlgItem( hwnd, IDW_OK ), FALSE ); if( Player[CurrentPlayer][IS_COMPUTER] ) { PCTurn = TRUE; EnableWindow( GetDlgItem( hwnd, IDW_ROLL ), FALSE ); } else { EnableWindow( GetDlgItem( hwnd, IDW_ROLL ), TRUE ); } }