void AI::obedientZombie(int index, std::deque<int> myOrders) { int x, y, humanIndex, wallIndex; Zombie* me = &zombies[index]; switch (myOrders.front()) { case 0: x = nextX(me->x(), me->y(), me->facing()); y = nextY(me->x(), me->y(), me->facing()); humanIndex = getHuman(x, y); if (humanIndex > -1) { myOrders.clear(); me->attack(humans[humanIndex]); } else me->move(); break; case 1: me->turn(-1); break; case 2: me->turn(1); break; } if (myOrders.size() > 0) myOrders.pop_front(); if (myOrders.size() > 0) orders[me->id()] = myOrders; else orders.erase(me->id()); }
void Arena::moveZombies() { // Move all zombies for (int k = m_nZombies - 1; k >= 0; k--) { Zombie* zp = m_zombies[k]; zp->move(); if (m_player != nullptr && zp->row() == m_player->row() && zp->col() == m_player->col()) m_player->setDead(); if (zp->isDead()) { m_history.record(zp->row(), zp->col()); delete zp; // The order of Zombie pointers in the m_zombies array is // irrelevant, so it's easiest to move the last pointer to // replace the one pointing to the now-deleted zombie. Since // we are traversing the array from last to first, we know this // last pointer does not point to a dead zombie. m_zombies[k] = m_zombies[m_nZombies - 1]; m_nZombies--; } } // Another turn has been taken m_turns++; }
//Zombie i is given orders based on an A* search to the nearest human // where nearest is defined by the zombieDistance function //Smart zombies will not break down walls, and will do nothing if // no path is available to the nearest human. void AI::smartZombie(int index) { const int FORGET = 5; //forget the last x of the generated path. const int REMEMBER = 5; //go no more than x turns without recalulating path int forgotten = 0; Zombie* me = &zombies[index]; Human* target = NULL; int bestDis = 9999999; int nextDis; int x, y, humanIndex, wallIndex; std::deque<int> path; std::cout << "smart" << std::endl; for (int i = 0; i < humans.size(); i++) { nextDis = zombieDistance(me->x(), me->y(), humans[i].x(), humans[i].y(), me->facing()); if (nextDis < bestDis) { bestDis = nextDis; target = &humans[i]; } } if (target != NULL) { path = findZombiePath(me->x(), me->y(), target->x(), target->y(), me->facing()); std::cout << "(" << me->x() << "," << me->y() << "," << target->x() << "," << target->y() << "," << me->facing() << ") = "; for (int k = 0; k < path.size(); k++) { std::cout << path[k] << " "; } if (path.size() == 0) { std::cout << "No action"; } std::cout << std::endl; if (path.size() > 1) { path.pop_front(); switch (path.front()) { case 0: x = nextX(me->x(), me->y(), me->facing()); y = nextY(me->x(), me->y(), me->facing()); humanIndex = getHuman(x, y); wallIndex = getWall(x, y); if (humanIndex > -1) me->attack(humans[humanIndex]); else if (wallIndex > -1) me->attack(walls[wallIndex]); else me->move(); break; case 1: me->turn(-1); break; case 2: me->turn(1); break; } /* while (path.size() > 0 && forgotten < FORGET) { path.pop_back(); forgotten += 1; } while (path.size() > REMEMBER) { path.pop_back(); } if (path.size() > 0) orders[me->id()] = path; */ } } std::cout << "end" << std::endl; }