void __fastcall TFormMain::TimerThinkerTimer(TObject *Sender) { //Check if moves already have been calculated if (mNextRobotMove.x!=-1) return; if (mNextRobotMove.y!=-1) return; if (IsRobot(mPlayer)==false) { OutputDebugString("Hey, I ain't a player!"); return; } int xMove = -1; int yMove = -1; //Make a non-random move if (xMove == -1 && yMove == -1) CheckTwoHorizontalOwn(xMove,yMove); if (xMove == -1 && yMove == -1) CheckTwoVerticalOwn(xMove,yMove); if (xMove == -1 && yMove == -1) CheckTwoOther(xMove,yMove); if (xMove == -1 && yMove == -1) CheckTwoDiagonally(xMove,yMove); if (xMove == -1 && yMove == -1) CheckOneOther(xMove,yMove); if (xMove == -1 && yMove == -1) MakeRandomMove(xMove,yMove); assert(IsValidMove(xMove,yMove)); //Do it then... mNextRobotMove.x = xMove; mNextRobotMove.y = yMove; //Click it on the playfield virtually //This will be done by TimerDoer }
void __fastcall TFormMain::TimerDebugTimer(TObject *Sender) { String s = "Debug: "; s+=" TimerThinker: "; s+=(TimerThinker->Enabled ? "Y" : "N"); s+=" TimerDoer: ";s+=(TimerDoer->Enabled ? "Y" : "N"); s+=" Player: ";s+= GetName(mPlayer); s+=" IsRobot: ";s+=(IsRobot(mPlayer) ? "Y" : "N"); OutputDebugString(s.c_str()); }
//--------------------------------------------------------------------------- void TFormMain::CheckTwoOther(int& xMove,int& yMove) const { assert(xMove == -1 && yMove == -1); const std::vector<GameMove> moves1(GetTwoHorizontalOtherMoves()); const std::vector<GameMove> moves2(GetTwoVerticalOtherMoves()); const std::vector<GameMove> moves(Concatenate(moves1,moves2)); assert(moves.size() == moves1.size() + moves2.size()); const int nMoves = moves.size(); if (nMoves==0) return; { //Get moves anti-player std::vector<GameMove> antiPlayerMoves; for (int i=0; i<nMoves; ++i) { assert(IsValidMove(moves[i])); if (IsRobot(moves[i].anti) == false) antiPlayerMoves.push_back(moves[i]); } //If there are anti-player moves, choose one at random if (antiPlayerMoves.empty()==false) { const int nAntiPlayerMoves = antiPlayerMoves.size(); const int index = std::rand() % nAntiPlayerMoves; xMove = antiPlayerMoves[index].x; yMove = antiPlayerMoves[index].y; assert(IsValidMove(xMove,yMove)); return; } } { //Get moves anti-next-player std::vector<GameMove> antiNextPlayerMoves; for (int i=0; i<nMoves; ++i) { if (GetNextPlayer(mPlayer) == moves[i].anti) antiNextPlayerMoves.push_back(moves[i]); } //If there are anti-next-player moves, choose one at random if (antiNextPlayerMoves.empty()==false) { const int nAntiNextPlayerMoves = antiNextPlayerMoves.size(); const int index = std::rand() % nAntiNextPlayerMoves; xMove = antiNextPlayerMoves[index].x; yMove = antiNextPlayerMoves[index].y; assert(IsValidMove(xMove,yMove)); return; } } //Choose a move at random { const int index = std::rand() % nMoves; xMove = moves[index].x; yMove = moves[index].y; assert(IsValidMove(xMove,yMove)); } }
string RobotWorld::GetName(int id) const { int i = IsRigidObject(id); if(i >= 0) return rigidObjects[i].name; i = IsTerrain(id); if(i >= 0) return terrains[i].name; i = IsRobot(id); if(i >= 0) return robots[i].name; pair<int,int> j = IsRobotLink(id); if(j.first >= 0) return robots[j.first].name+"["+robots[j.first].robot->linkNames[j.second]+"]"; return ""; }
//--------------------------------------------------------------------------- const String TFormMain::GetName(const EnumBlock player) const { assert(player!=NoPlayer); if (IsRobot(player)==true) return "Robot"; switch (player) { case Player1: return "Speler 1"; case Player2: return "Speler 2"; case Player3: return "Speler 3"; default: assert(!"Should not get here"); } assert(!"Should not get here"); return "Richel"; }
//--------------------------------------------------------------------------- __fastcall TFormMain::TFormMain( TComponent* Owner, const bool player1_human, const bool player2_human, const bool player3_human) : TForm(Owner), m_player1_human(player1_human), m_player2_human(player2_human), m_player3_human(player3_human), mBlocks(16, std::vector<EnumBlock>(12,NoPlayer)), mPlayer(Player1), mMaxx(16), mMaxy(12) { std::srand(std::clock()); mNextRobotMove.x = -1; mNextRobotMove.y = -1; ImageBuffer->Picture->Bitmap->Width = 800; ImageBuffer->Picture->Bitmap->Height = 600; DrawScreen(); if (IsRobot(mPlayer)) TimerThinker->Enabled = true; }
//--------------------------------------------------------------------------- void TFormMain::CheckOneOther(int& xMove,int& yMove) const { assert(xMove == -1 && yMove == -1); std::vector<GameMove> moves; for (int y=0; y!=mMaxy; ++y) { for (int x=0; x!=mMaxx; ++x) { if (mBlocks[x][y] != NoPlayer) { if (y >= 1) { if (mBlocks[x][y-1] == NoPlayer) { GameMove move; move.x = x; move.y = y-1; move.anti = mBlocks[x][y]; assert(IsValidMove(move)); moves.push_back(move); } } if (y < mMaxy-1) { if (mBlocks[x][y+1] == NoPlayer) { GameMove move; move.x = x; move.y = y+1; move.anti = mBlocks[x][y]; assert(IsValidMove(move)); moves.push_back(move); } } if (x >= 1) { if (mBlocks[x-1][y] == NoPlayer) { GameMove move; move.x = x-1; move.y = y; move.anti = mBlocks[x][y]; assert(IsValidMove(move)); moves.push_back(move); } } if (x < mMaxx-1) { if (mBlocks[x+1][y] == NoPlayer) { GameMove move; move.x = x+1; move.y = y; move.anti = mBlocks[x][y]; assert(IsValidMove(move)); moves.push_back(move); } } } } } const int nMoves = moves.size(); if (nMoves == 0) return; { //Get moves anti-player std::vector<GameMove> antiPlayerMoves; for (int i=0; i<nMoves; ++i) { if (IsRobot(moves[i].anti) == false) antiPlayerMoves.push_back(moves[i]); } //If there are anti-player moves, choose one at random if (antiPlayerMoves.empty()==false) { const int nAntiPlayerMoves = antiPlayerMoves.size(); const int index = std::rand() % nAntiPlayerMoves; xMove = antiPlayerMoves[index].x; yMove = antiPlayerMoves[index].y; assert(IsValidMove(antiPlayerMoves[index])); return; } } { //Get moves anti-next-player std::vector<GameMove> antiNextPlayerMoves; for (int i=0; i<nMoves; ++i) { if (GetNextPlayer(mPlayer) == moves[i].anti) antiNextPlayerMoves.push_back(moves[i]); } //If there are anti-next-player moves, choose one at random if (antiNextPlayerMoves.empty()==false) { const int nAntiNextPlayerMoves = antiNextPlayerMoves.size(); const int index = std::rand() % nAntiNextPlayerMoves; xMove = antiNextPlayerMoves[index].x; yMove = antiNextPlayerMoves[index].y; assert(IsValidMove(antiNextPlayerMoves[index])); return; } } //Choose a move at random { const int index = std::rand() % nMoves; xMove = moves[index].x; yMove = moves[index].y; assert(IsValidMove(xMove,yMove)); } }
//--------------------------------------------------------------------------- void __fastcall TFormMain::FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { //When the AI is 'thinking' no clicks are allowed if (IsRobot(mPlayer)==true && Sender->ClassNameIs("TTimer")==false) return; //ImageBuffer->Visible = false; const int x = X / 50; const int y = Y / 50; //Is this a relevant move? if (mBlocks[x][y] != NoPlayer) return; // Yes, a relevant move mBlocks[x][y] = mPlayer; mPlayer = GetNextPlayer(mPlayer); //Start the AI robot! if (IsRobot(mPlayer)) TimerThinker->Enabled = true; DrawScreen(); //Check for three on a row { for (int y=0; y!=mMaxy; ++y) { for (int x=0; x!=mMaxx; ++x) { if (mBlocks[x][y] == NoPlayer) continue; EnumBlock winner = NoPlayer; //Horizontal if (x + 2 < mMaxx && mBlocks[x][y] == mBlocks[x+1][y] && mBlocks[x+1][y] == mBlocks[x+2][y]) { winner = mBlocks[x][y]; } //Vertical if (y + 2 < mMaxy && mBlocks[x][y] == mBlocks[x][y+1] && mBlocks[x][y+1] == mBlocks[x][y+2]) { winner = mBlocks[x][y]; } if (winner!=NoPlayer) { //A winner has been found! TimerDoer->Enabled = false; TimerThinker->Enabled = false; boost::scoped_ptr<TFormGewonnen> formGewonnen( new TFormGewonnen(0,static_cast<int>(winner),!IsRobot(winner))); formGewonnen->Hide(); formGewonnen->ShowModal(); //Show FormStoppen boost::scoped_ptr<TFormStoppen> formStoppen(new TFormStoppen(0)); formStoppen->Hide(); formStoppen->ShowModal(); if (formStoppen->ModalResult == 1) { //Nog een keer TimerDoer->Enabled = true; mBlocks = std::vector<std::vector<EnumBlock> >(16, std::vector<EnumBlock>(12,NoPlayer)); mPlayer = Player1; if (IsRobot(mPlayer)) TimerThinker->Enabled = true; DrawScreen(); } else { //Stoppen ModalResult = 1; } } } } } }