DWORD CTeleportPath::FindTeleportPath(POINT ptStart, POINT ptEnd, LPPOINT lpBuffer, DWORD dwMaxCount) { if (lpBuffer == NULL || dwMaxCount == 0 || m_nCX <= 0 || m_nCY <= 0 || m_ppTable == NULL) return 0; memset(lpBuffer, 0, sizeof(POINT) * dwMaxCount); m_ptStart = ptStart; m_ptEnd = ptEnd; //GameInfof("start %d %d End %d %d", ptStart.x, ptStart.y, ptEnd.x, ptEnd.y); MakeDistanceTable(); lpBuffer[0] = ptStart; // start point DWORD dwFound = 0; POINT pos = ptStart; BOOL bOK = FALSE; int nRes = GetBestMove(pos); while (nRes != PATH_FAIL && dwFound < dwMaxCount) { // Reached? if (nRes == PATH_REACHED) { bOK = TRUE; lpBuffer[dwFound] = ptEnd; dwFound++; break; // Finished } // Perform a redundancy check int nRedundancy = GetRedundancy(lpBuffer, dwFound, pos); if (nRedundancy == -1) { // no redundancy lpBuffer[dwFound] = pos; dwFound++; } else { // redundancy found, discard all redundant steps dwFound = nRedundancy + 1; lpBuffer[dwFound] = pos; } nRes = GetBestMove(pos); } if (!bOK) dwFound = 0; return dwFound; }
void AI_DoMove(tMove *MyMove) { #if 1 // Sanity checks for( int i = 0; i < N_PIECES; i ++ ) { tPiece *p = &gpCurrentGameState->MyActual.Pieces[i]; if(p->bDead) continue; if( p != GetPieceByPos(p->X, p->Y) ) { DEBUG("Piece %p(%i,%i R%i) not at stated position", p, p->X, p->Y, p->Rank); } } #endif DEBUG("Deciding on move"); GetBestMove(&gpCurrentGameState->MyActual, &gpCurrentGameState->Opponent, MyMove, 0); }
ab::Acceleration ab::PredictiveStrategy::GetTurn(const ab::FieldState& state, const ab::PlayerId player_id) { size_t players_number = state.players.size(); std::vector<BestMoveToCoin> best_moves; for (size_t player_index = 0; player_index < players_number; ++player_index) best_moves.push_back(GetBestMove(state, player_index)); int aim_coin = best_moves[player_id].coin_id; if (-1 == aim_coin) { return MoveToClosestCoin(state, player_id); } double best_time_to_coin = best_moves[player_id].best_time; for (size_t player_index = 0; player_index < players_number; ++player_index) { if (best_moves[player_index].coin_id == aim_coin && best_moves[player_index].best_time < best_time_to_coin) { return MoveToClosestCoin(state, player_id); } } return best_moves[player_id].best_acceleration; }
//****************************************************************************************** void CRoachQueen::GetBrainDirectedMovement( // Special-cased for roach queens. // //Params: int &dxFirst, //(out) Horizontal delta for where the monster would // go if there weren't obstacles. int &dyFirst, //(out) Vertical delta for same. int &dx, //(out) Horizontal delta (-1, 0, or 1) for where monster // can go, taking into account obstacles. int &dy) //(out) Vertical delta (-1, 0, or 1) for same. const { SQUARE square; this->pCurrentGame->pRoom->pPathMap[this->eMovement]->GetSquare(this->wX, this->wY, square); if (square.eState == ok && square.eDirection != none) { //Run away from swordsman, based on the direction of the pathmap. dx = -nGetOX(square.eDirection); dy = -nGetOY(square.eDirection); //Try to move diagonally toward middle of the room on non-primary axis. if (dx == 0) dx = (wX < (this->pCurrentGame->pRoom->wRoomCols / 2)) ? 1: -1; else if (dy == 0) dy = (wY < (this->pCurrentGame->pRoom->wRoomRows / 2)) ? 1: -1; dxFirst = dx; dyFirst = dy; } else { //With a brain, even invisible swordsman is sensed. dx = dxFirst = -sgn(this->pCurrentGame->swordsman.wX - this->wX); dy = dyFirst = -sgn(this->pCurrentGame->swordsman.wY - this->wY); } GetBestMove(dx, dy); }
//***************************************************************************************** void CRoachQueen::Process( //Process a roach queen for movement. // //Params: const int nLastCommand, //(in) Last swordsman command. CCueEvents &CueEvents) //(in/out) Accepts pointer to an IDList object that will be populated //with codes indicating events that happened that may correspond to //sound or graphical effects. { //Get movement offsets. int dxFirst, dyFirst, dx, dy; if (this->pCurrentGame->pRoom->IsBrainPresent()) GetBrainDirectedMovement(dxFirst, dyFirst, dx, dy); else { if (CanFindSwordsman()) { // Run away! dx = dxFirst = -sgn(this->pCurrentGame->swordsman.wX - this->wX); dy = dyFirst = -sgn(this->pCurrentGame->swordsman.wY - this->wY); GetBestMove(dx, dy); } else return; //no change -- and don't lay eggs } // Save previous location const UINT oX = this->wX; const UINT oY = this->wY; //Move roach queen to new destination square. MakeStandardMove(CueEvents,dx,dy); SetOrientation(dxFirst, dyFirst); //Shall we lay some eggs? //The criteria for laying an egg in a square should be: //1. Square does not contain a monster (including mimic). //2. Square does not contain a swordsman or sword. //3. Square does not contain a mimic sword. //4. T-square is T_EMPTY. //5. O-square is T_FLOOR. if ((this->pCurrentGame->wSpawnCycleCount % TURNS_PER_CYCLE == 0) && CanFindSwordsman()) { for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { const UINT ex = this->wX + x; const UINT ey = this->wY + y; if (//Valid this->pCurrentGame->pRoom->IsValidColRow(ex, ey) && // Not current queen position !(ex == this->wX && ey == this->wY) && // Not old queen position (compat) !(ex == oX && ey == oY) && // Not swordsman !(ex == this->pCurrentGame->swordsman.wX && ey == this->pCurrentGame->swordsman.wY) && // Not monster or mimic or sword !DoesSquareContainObstacle(ex, ey) && //And t-square is empty (compat). this->pCurrentGame->pRoom->GetTSquare(ex, ey) == T_EMPTY && //And o-square is floor (compat). this->pCurrentGame->pRoom->GetOSquare(ex, ey) == T_FLOOR ) { // Place an egg CMonster *m = this->pCurrentGame->pRoom->AddNewMonster(M_REGG, ex,ey); m->SetCurrentGame(this->pCurrentGame); m->bIsFirstTurn = true; } } } } }
BYTE CPathFinder::CalculatePathTo(WORD x, WORD y, LPPATH lpBuffer, int nAdjust) { if (lpBuffer == NULL || x == 0 || y == 0 || !VerifyMemory()) return 0; memset(lpBuffer, 0, sizeof(PATH)); lpBuffer->posStart = GetPosition(); if (lpBuffer->posStart.x == 0 || lpBuffer->posStart.y == 0) return 0; if (!Search()) return 0; //GameInfof("Mapsize %d, %d", m_rightBottom.x - m_lefttTop.x, m_rightBottom.y - m_lefttTop.y); m_ptAbsDest.x = x; m_ptAbsDest.y = y; m_ptRelDest = m_ptAbsDest; MapToGraph(m_ptRelDest); //GameInfof("des %d, %d", m_ptRelDest.x, m_ptRelDest.y); // verify destination, see if it's in our map if (!IsValidPos(m_ptRelDest)) return 0; MakeMap2(); //DumpMap2(); POINT pos; pos.x = (short)lpBuffer->posStart.x; pos.y = (short)lpBuffer->posStart.y; lpBuffer->iNodeCount = 0; BOOL bOK = FALSE; int nRes = GetBestMove(pos, nAdjust); while (nRes != PATH_FAIL && lpBuffer->iNodeCount < 255) { // Reached? if (nRes == PATH_REACHED) { bOK = TRUE; lpBuffer->aPathNodes[lpBuffer->iNodeCount].x = x; lpBuffer->aPathNodes[lpBuffer->iNodeCount].y = y; lpBuffer->iNodeCount++; break; // Finished } // Perform a redundancy check int nRedundancy = GetRedundancy(lpBuffer, pos); if (nRedundancy == -1) { // no redundancy lpBuffer->aPathNodes[lpBuffer->iNodeCount].x = (WORD)pos.x; lpBuffer->aPathNodes[lpBuffer->iNodeCount].y = (WORD)pos.y; lpBuffer->iNodeCount++; } else { // redundancy found, discard all redundant steps lpBuffer->iNodeCount = nRedundancy + 1; lpBuffer->aPathNodes[lpBuffer->iNodeCount].x = (WORD)pos.x; lpBuffer->aPathNodes[lpBuffer->iNodeCount].y = (WORD)pos.y; } nRes = GetBestMove(pos, nAdjust); } if (!bOK) { lpBuffer->iNodeCount = 0; } else { lpBuffer->posEnd.x = x; lpBuffer->posEnd.y = y; } //DumpMap1(lpBuffer); // debug pictures return lpBuffer->iNodeCount; }
//***************************************************************************************** void CMimic::Process( //Process a mimic for movement. // //Params: const int nLastCommand, //(in) Last swordsman command. CCueEvents &CueEvents) //(in/out) Accepts pointer to an cues object that will be populated //with codes indicating events that happened that may correspond to //sound or graphical effects. { int dx=0, dy=0; switch (nLastCommand) { case CMD_C: { this->wO = nNextCO(this->wO); break; } case CMD_CC: { this->wO = nNextCCO(this->wO); break; } case CMD_NW: dx = dy = -1; break; case CMD_N: dy = -1; break; case CMD_NE: dx = 1; dy = -1; break; case CMD_W: dx = -1; break; case CMD_E: dx = 1; break; case CMD_SW: dx = -1; dy = 1; break; case CMD_S: dx = 0; dy = 1; break; case CMD_SE: dx = dy = 1; break; } const UINT wMovementO = nGetO(dx, dy); if (this->bFrozen) //frozen by aumtlich gaze? dx = dy = 0; CDbRoom& room = *(this->pCurrentGame->pRoom); // Did the nLastCommand successfully move the swordsman. // If not, then set dx/dy to zero so mimics don't move if (this->pCurrentGame->IsPlayerAt(this->pCurrentGame->swordsman.wPrevX, this->pCurrentGame->swordsman.wPrevY)) { dx=dy=0; this->wPrevX = this->wX; this->wPrevY = this->wY; //Player bumped into something, so mimics can "bump" into something in this //direction too, i.e. shatter a mirror in this direction if their sword is on it. this->wSwordMovement = CSwordsman::GetSwordMovement(nLastCommand, this->wO); if (nLastCommand != CMD_C && nLastCommand != CMD_CC && this->wSwordMovement != this->wO) //if not a turning or bumping movement this->wSwordMovement = NO_ORIENTATION; if (!HasSword() && wMovementO != NO_ORIENTATION) //they can face this direction when swordless this->wO = wMovementO; } else { GetBestMove(dx, dy); this->wSwordMovement = nGetO(dx, dy); //Check for obstacles in destination square. if (dx || dy) { ASSERT(nLastCommand != CMD_C && nLastCommand != CMD_CC && nLastCommand != CMD_WAIT && nLastCommand != CMD_EXEC_COMMAND); //Before he moves, remember important square contents. const UINT wOTile = room.GetOSquare(this->wX, this->wY); const bool bWasOnTrapdoor = bIsTrapdoor(wOTile); const bool bWasOnPlatform = bIsPlatform(wOTile); //Move mimic to new destination square. Move(this->wX + dx, this->wY + dy, &CueEvents); if (!HasSword()) this->wO = nGetO(dx,dy); //face the direction moved when w/o sword ASSERT(IsValidOrientation(this->wO)); //Check for movement off of a trapdoor. ASSERT(dx || dy); if (bWasOnTrapdoor && HasSword()) room.DestroyTrapdoor(this->wX - dx, this->wY - dy, CueEvents); //Check for platform movement. if (bWasOnPlatform) { const UINT wOTile = room.GetOSquare(this->wX, this->wY); if (bIsPit(wOTile) || bIsDeepWater(wOTile)) room.MovePlatform(this->wX - dx, this->wY - dy, nGetO(dx,dy)); } //Check for movement onto a checkpoint. this->pCurrentGame->QueryCheckpoint(CueEvents, this->wX, this->wY); //Process any and all of these item interactions. UINT tTile = room.GetTSquare(this->wX, this->wY); if (tTile==T_MIRROR) { room.PushObject(this->wX, this->wY, this->wX + dx, this->wY + dy, CueEvents); tTile = room.GetTSquare(this->wX, this->wY); //also check what was under the mirror } if (tTile==T_TOKEN) room.ActivateToken(CueEvents, this->wX, this->wY); } else { this->wPrevX = this->wX; this->wPrevY = this->wY; //Mimics can smash mirrors by bumping into them even when they don't move. this->wSwordMovement = CSwordsman::GetSwordMovement(nLastCommand, this->wO); if (nLastCommand != CMD_C && nLastCommand != CMD_CC && this->wSwordMovement != this->wO) this->wSwordMovement = NO_ORIENTATION; if (!HasSword() && wMovementO != NO_ORIENTATION) //they can face this direction when swordless this->wO = wMovementO; } } //Light any fuse stood on. room.LightFuse(CueEvents, this->wX, this->wY, true); }