home *** CD-ROM | disk | FTP | other *** search
- // ObjectWindows - (C) Copyright 1992 by Borland International
-
- #include <windows.h>
- #include <time.h>
- #include <stdio.h>
- #include <string.h>
- #include "wcdefs.h"
- #include "wchess.h"
- #include "externs.h"
-
- /*
- * Global Variables
- */
-
-
- MOVETYPE ZeroMove = { 8, 8, 0, empty, empty };
- CLOCKTYPE ChessTime[2];
- MOVETYPE KeyMove;
- BOOL Running;
- COLORTYPE RunColor;
- BOOL Analysis, Opan;
- double WantedTime;
- extern double AverageTime;
- BOOL GameOver = FALSE;
- char EndGameMessage[80];
-
-
- void EndMessage(char *);
-
- /*
- * Initialize the chess clocks
- */
-
- void InitChessTime()
- {
- InitTime(&ChessTime[white]);
- InitTime(&ChessTime[black]);
- }
-
- void StopChessTime()
- {
- if (Running)
- {
- StopTime(&ChessTime[RunColor]);
- KillTimer(hWndMain, TIMEID);
- Running = FALSE;
- }
- }
-
- /*
- * Stop the running chess clock and start the clock for color
- */
-
- void StartChessTime(COLORTYPE color)
- {
- RunColor = color;
- Running = TRUE;
- StartTime(&ChessTime[RunColor]);
- SetTimer(hWndMain, TIMEID, 1000, NULL);
- }
-
- /*
- * reset MovTab
- */
-
- void ResetMoves()
- {
- Depth = -1;
- MovTab[-1] = ZeroMove;
- }
-
-
- /*
- * Clear HintLine
- */
-
- void ClearHint()
- {
- HintLine[0] = ZeroMove;
- HintEvalu = 0;
- }
-
- void InitNode(NODEVAL *nodes)
- {
- nodes->nodebase = 0;
- nodes->nodeoffset = 0;
- }
-
- /*
- * Test if the move is legal for Programcolor == player in the
- * given position
- */
-
- BOOL IllegalMove(MOVETYPE *move)
- {
- BOOL illegal;
-
- Perform(move, 0);
- illegal = Attacks(Opponent, PieceTab[Player][0].isquare);
- Perform(move, 1);
- return illegal;
- }
-
-
-
- /*
- * Make move for programcolor = player and updates variables
- */
-
- void MakeMove(MOVETYPE *move)
- {
- Depth++;
- MoveNo++;
- Perform(move, 0);
- ProgramColor = Opponent;
- Opponent = Player;
- Player = ProgramColor;
- }
-
-
- /*
- * Prints comment to the game (check, mate, draw, resign)
- */
-
- void PrintComment(void)
- {
- extern char buf[];
- short check, possiblemove, checkmate;
- int nummoves;
-
- Message("");
- checkmate = 0;
- Depth++;
- possiblemove = 0;
- InitMovGen();
- do
- {
- MovGen();
- if (Next.movpiece != empty)
- if (!IllegalMove(&Next))
- possiblemove = 1;
- } while (Next.movpiece != empty && !possiblemove);
-
- Depth--;
- check = Attacks(Opponent, PieceTab[Player][0].isquare); /* calculate check */
- /* No possible move means checkmate or stalemate */
- if (!possiblemove)
- {
- if (check)
- {
- checkmate = 1;
- EndMessage("CheckMate");
- }
- else
- EndMessage("Stalemate!");
- }
- else
- if (HintEvalu >= MATEVALUE - DEPTHFACTOR * 16)
- {
- nummoves = (MATEVALUE - HintEvalu + 0x40) / (DEPTHFACTOR * 2);
- sprintf(buf, "Mate in %d Move%c", nummoves, (nummoves > 1) ? 's!':'!');
- Message(buf);
- }
- if (check && !checkmate)
- Message("Check!");
- else /* test 50 move rule and repetition of moves */
- {
- if (FiftyMoveCnt() >= 100)
- {
- EndMessage("50 Move rule");
- }
- else
- if (Repetition(0) >= 3)
- {
- EndMessage("3 fold Repetition");
- }
- else /* Resign if the position is hopeless */
- if (-25500 < HintEvalu && HintEvalu < -0x880)
- {
- switch (Opponent)
- {
- case white :
- EndMessage(" White resigns");
- break;
- case black :
- EndMessage(" Black resigns");
- }
- }
- }
- }
-
- void EnterMove(MOVETYPE *move)
- {
- StopChessTime();
- PrintMove(MoveNo, ProgramColor, move, ChessTime[RunColor].totaltime);
- MakeMove(move);
- UpdateBoard();
- PrintComment();
- StartChessTime(ProgramColor);
- }
-
- void RemoveMove(MOVETYPE *move)
- {
- StopChessTime();
- PrintMove(MoveNo, ProgramColor, move, ChessTime[RunColor].totaltime);
- TakeBackMove(move);
- UpdateBoard();
- PrintComment();
- StartChessTime(ProgramColor);
- }
-
- /*
- * perform the move entered by the user
- */
-
- void EnterKeyMove(void)
- {
- MovTab[Depth+1] = KeyMove;
- PlayerMove = KeyMove;
- ClearHint();
- DragEnd(TRUE);
- EnterMove(&MovTab[Depth+1]);
- }
-
-
- /*
- * move movtab to depth = -1
- */
-
- void AdjustMoves()
- {
- int i;
-
- for (i = Depth; i>= BACK; i--)
- MovTab[i - (Depth+1)] = MovTab[i];
- Depth = -1;
- }
-
-
- /*
- * Move movtab one move BACK
- */
-
-
- void StoreMoves(void)
- {
- int i;
- Depth--;
- for (i = BACK; i <= Depth; i++)
- MovTab[i] = MovTab[i+1];
- MovTab[BACK] = ZeroMove;
- }
-
-
- /*
- * Check to see if the input move is legal
- */
-
- BOOL MoveCheck(SQUARETYPE startsq, SQUARETYPE endsq)
- {
- Depth++;
- KeyMove = ZeroMove;
- InitMovGen();
- do
- {
- MovGen();
- if (Next.new1 == endsq && Next.old == startsq)
- {
- KeyMove = Next;
- break;
- }
- } while (Next.movpiece != empty);
- if (KeyMove.movpiece == empty)
- {
- Warning("Impossible move");
- Depth--;
- return FALSE;
- }
- if (IllegalMove(&KeyMove))
- {
- Warning("Illegal move. Check!");
- Depth--;
- return FALSE;
- }
- Depth--;
- if (!ComputerThinking)
- {
- AdjustMoves();
- EnterKeyMove();
- StoreMoves();
- }
- return TRUE;
- }
-
-
- /*
- * calculate the WANTED response time
- */
-
- void StartAnalysis()
- {
- int timecontrol;
- extern HWND hWndMain;
- extern HCURSOR hWaitCursor;
-
- Analysis = 1;
- Opan = 0;
- SetClassWord(hWndMain, GCW_HCURSOR, WORD(hWaitCursor));
- SetCursor(hWaitCursor);
- switch (Level)
- {
- case easygame :
- case normal :
- /* Divides the Time left till nest time control
- between moves left. There is a margin of
- 4 moves to make sure that the program does
- not lose on time */
- timecontrol = (((MoveNo >> 1) + 20) / 20) * 20;
- if (timecontrol <= 40) timecontrol = 40;
- WantedTime = (AverageTime * timecontrol -
- ChessTime[ProgramColor].totaltime) /
- (timecontrol + 4 - (MoveNo >> 1));
-
- /* In the begining of the game the program thinks
- around twice as long, since the early middle
- game is normally the most crucial part of
- a game */
-
- if ((MoveNo >> 1) <= 40)
- WantedTime = 5.0 + (WantedTime - 5.0) *
- ((80 - (MoveNo >> 1)) /40);
- break;
- case fullgametime :
- /* Assumes that the game will last for around 40 moves and
- divides the time left accordingly */
- WantedTime = (AverageTime * 60.0 -
- ChessTime[ProgramColor].totaltime) / 44;
-
- /* In the begining of the game the program thinks
- around twice as long, since the early middle
- game is normally the most crucial part of
- a game */
- if ((MoveNo >> 1) <= 40)
- WantedTime = 5.0 + (WantedTime - 5.0) *
- ((80 - (MoveNo >> 1)) /40);
- break;
- case matching :
- /* Spend as much time as the Opponent does */
- if (MoveNo >= 2)
- WantedTime = ChessTime[Opponent].totaltime / (MoveNo >> 1);
- else
- WantedTime = 5.0;
- WantedTime += (ChessTime[Opponent].totaltime -
- ChessTime[ProgramColor].totaltime) * 0.25;
- default :
- WantedTime = 1000000.0;
- }
- }
-
-
- /*
- * take BACK move and update variables
- */
-
- void TakeBackMove(MOVETYPE *move)
- {
- ProgramColor = Opponent;
- Opponent = Player;
- Player = ProgramColor;
- Perform(move, 1);
- MoveNo--;
- Depth--;
- }
-
-
- void IncNode(NODEVAL *nodes)
- {
- if (nodes->nodeoffset >= MAXINT)
- {
- nodes->nodebase++;
- nodes->nodeoffset = 0;
- }
- else
- nodes->nodeoffset++;
- }
-
-
- void Wait(int tenths)
- {
- clock_t NumTicksToWait;
-
- /* two ticks == approx. 1/10 second, since 18.2 clocks is approx a
- second */
- NumTicksToWait = (tenths * 2) + clock();
- while (NumTicksToWait > clock()) ;
- }
-
-
- /*
- * Flash a move once on the screen
- */
-
- void FlashMove(MOVETYPE *move)
- {
- MakeMove(move);
- UpdateBoard();
- Wait(4);
- TakeBackMove(move);
- UpdateBoard();
- Wait(4);
- }
-
- void DoSlideMove(MOVETYPE &move)
- {
- SQUARETYPE castsquare, cornersquare;
- SlidePiece(move.new1, move.old);
- if (move.spe)
- {
- if (move.movpiece == king)
- {
- GenCastSquare(move.new1, &castsquare, &cornersquare);
- SlidePiece(castsquare, cornersquare);
- }
- }
- }
-
- void EndMessage(char *message)
- {
- strcpy(EndGameMessage, message);
- GameOver = TRUE;
- }
-
-
- void ShowHint()
- {
- DEPTHTYPE dep = 0;
- buf[0] = '\0';
- Message(buf);
- while (HintLine[dep].movpiece != empty)
- {
- strcat(buf, MoveStr(&HintLine[dep]));
- strcat(buf, " ");
- Message(buf);
- MakeMove(&HintLine[dep]);
- UpdateBoard();
- Wait(6);
- dep++;
- }
- while (dep > 0)
- {
- dep--;
- TakeBackMove(&HintLine[dep]);
- }
- UpdateBoard();
- }
-