void PlayerCharacterEntity::update() { m_velocity = ((float)m_health + 10)/m_velocityModifier; if (m_controlledByAI == true) { // this is a bot character, here's the AI! :D // set check surroundings timer to one of two primes m_checkTimer--; if (m_checkTimer <= 0) { m_checkTimer = (rand()%2 > 0) ? 37 : 67; checkEnvironment(); } if (m_goalList.empty() && m_insList.empty()) { determineGoals(); } if (m_insList.empty()) { determineInstructionsFromGoal(); } // add AI for important surroundings sensing whateverness processNextInstruction(); } }
static void instructionMove() { checkToMap(self); setCustomAction(&player, &helpless, 5, 0, 0); if (self->dirX == 0 && self->dirY == 0) { processNextInstruction(); } else if (self->x == self->endX && self->y == self->endY) { runScript("robot_end"); self->dirX = 0; self->dirY = 0; self->action = &entityWait; setEntityAnimation(self, "STAND"); activateEntitiesWithRequiredName(self->objectiveName, TRUE); centerMapOnEntity(&player); setPlayerLocked(FALSE); self->health = 2; self->target->inUse = FALSE; self->target = NULL; self->touch = NULL; self->activate = NULL; } }
void PlayerCharacterEntity::processNextInstruction() { if (m_insList.empty()) { return; } AIInstruction * ins = m_insList.front(); m_insList.pop_front(); switch (ins->m_type) { case AIInstruction::CREATE_ENTITY: { if (m_health < 15) { break; } // check if this tile already has a static entity bool staticAtLocation = this->staticEntityAtLocation(getTileX(), getTileY()); if (staticAtLocation) { // there is already a static entity // if this is an egg type required, move to nearest "empty" tile if ( ins->m_targetType == EGG1 || ins->m_targetType == EGG2 || ins->m_targetType == EGG3 || ins->m_targetType == EGG4 || ins->m_targetType == EGG5 ) { // find nearest empty tile and move there, replace instruction if (goToNearestEmptyTile(ins->m_targetTileX, ins->m_targetTileY)) { // can go to an empty tile AIInstruction * copiedIns = new AIInstruction(*ins); // put CREATE instruction after GOTO at head of list AIInstruction * goToIns = m_insList.front(); m_insList.pop_front(); m_insList.push_front(copiedIns); m_insList.push_front(goToIns); } else { // failed to find a nearby empty tile // forget this instruction for now } } else { // is a weapon/block type // probably not very helpful to move location // so forget this instruction } } else { // there isn't a static entity // if this is an egg, is it a safe enough location? // is this a weapon? if so, check desired spot if (ins->m_targetType == BOMB || ins->m_targetType == BLOCK || ins->m_targetType == MINE || ins->m_targetType == ROCKET_SPIN) { if (ins->m_targetType == BOMB || ins->m_targetType == MINE) { if (!safeLocationToBomb(m_tileX, m_tileY)) { break; } } if (ins->m_targetTileX == m_tileX && ins->m_targetTileY == m_tileY) { createEntity(ins->m_targetType); } } else { // check this location is safe for an egg bool bombOrMineFound = false; for (int i = 0; i < 4; ++i) { int x, y; x = m_tileX; y = m_tileY; switch (i) { case 0: x++; break; case 1: x--; break; case 2: y++; break; case 3: y--; break; } vector<EntityInfo> eiVec = AIGameView::getInstance()->getEntityInfoAtLocation(x, y); vector<EntityInfo>::iterator it; for (it = eiVec.begin(); it != eiVec.end(); ++it) { // even our team's bombs and mines are dangerous to eggs if (it->type == BOMB || it->type == MINE) { bombOrMineFound = true; break; } } if (bombOrMineFound) { break; } } // end for 0..3 if (!bombOrMineFound) { createEntity(ins->m_targetType); } else { // move elsewhere AIInstruction * copy = new AIInstruction(*ins); m_insList.push_front(copy); goNumTilesAway(3); } } } } break; case AIInstruction::GO_TO: { // check for simple 0 or 1 tile movement int xDist, yDist; xDist = m_tileX - ins->m_targetTileX; yDist = m_tileY - ins->m_targetTileY; bool moved = false; if (xDist == 0 && yDist == 0) { // in target tile, close enough to center? if (nearTileCenter()) { // finished this instruction break; } else { // keep moving in current direction DIRECTION dir = static_cast<DIRECTION>(m_currentAnimState - 1); moveInDirection(dir); moved = true; } } // only one tile to go? // check target tile isn't blocked if (Map::getInstance()->staticTileAt(ins->m_targetTileX, ins->m_targetTileY) != Map::EMPTY) { break; } if (xDist == -1 && yDist == 0) { moveInDirection(RIGHT); moved = true; } else if (xDist == 1 && yDist == 0) { moveInDirection(LEFT); moved = true; } else if (xDist == 0 && yDist == 1) { moveInDirection(UP); moved = true; } else if (xDist == 0 && yDist == -1) { moveInDirection(DOWN); moved = true; } if (moved) { // copy instruction AIInstruction * copyIns = new AIInstruction(*ins); m_insList.push_front(copyIns); incAnimFrame(); break; } // there is a multiple tile distance, use path finding // get next tile by pathfinding coord next = getNextTileFromPathfinding(ins->m_targetTileX, ins->m_targetTileY); // did pathfinding work? if (next.first == getTileX() && next.second == getTileY()) { // did not work, or we're already where we want to be } else { // copy instruction AIInstruction * copyIns = new AIInstruction(*ins); m_insList.push_front(copyIns); // add this tile as goto AIInstruction * newIns = new AIInstruction(AIInstruction::GO_TO, 0, getType(), next.first, next.second); m_insList.push_front(newIns); processNextInstruction(); } } break; case AIInstruction::MOVE_FROM_LOCATION: { goNumTilesAway(ins->m_targetAmount); } break; case AIInstruction::WAIT: { int waitAmount = ins->m_targetAmount - 1; if (waitAmount > 0) { AIInstruction * newIns = new AIInstruction(ins->m_type, waitAmount, ins->m_targetType, ins->m_targetTileX, ins->m_targetTileY); m_insList.push_front(newIns); } // else nothing more to do } break; } delete ins; }