コード例 #1
0
ファイル: village_control.cpp プロジェクト: aravasio/keeperrl
void VillageControl::update(bool currentlyActive) {
  considerWelcomeMessage();
  considerCancellingAttack();
  checkEntries();
  if (Collective* enemy = getEnemyCollective())
    maxEnemyPower = max(maxEnemyPower, enemy->getDangerLevel());
  vector<Creature*> allMembers = getCollective()->getCreatures();
  for (auto team : getCollective()->getTeams().getAll()) {
    for (const Creature* c : getCollective()->getTeams().getMembers(team))
      if (!getCollective()->hasTask(c)) {
        getCollective()->getTeams().cancel(team);
        break;
      }
    return;
  }
  double updateFreq = 0.1;
  if (canPerformAttack(currentlyActive) && Random.roll(1 / updateFreq))
    if (villain) {
      double prob = villain->getAttackProbability(this) / updateFreq;
      if (prob > 0 && Random.roll(1 / prob)) {
        vector<Creature*> fighters;
        fighters = getCollective()->getCreatures({MinionTrait::FIGHTER}, {MinionTrait::SUMMONED});
        if (getCollective()->getGame()->isSingleModel())
          fighters = filter(fighters, [this] (const Creature* c) {
              return contains(getCollective()->getTerritory().getAll(), c->getPosition()); });
        Debug() << getCollective()->getName().getShort() << " fighters: " << int(fighters.size())
          << (!getCollective()->getTeams().getAll().empty() ? " attacking " : "");
        if (fighters.size() >= villain->minTeamSize && 
            allMembers.size() >= villain->minPopulation + villain->minTeamSize)
        launchAttack(getPrefix(Random.permutation(fighters),
          Random.get(villain->minTeamSize, min(fighters.size(), allMembers.size() - villain->minPopulation) + 1)));
      }
    }
}
コード例 #2
0
ファイル: village_control.cpp プロジェクト: aravasio/keeperrl
void VillageControl::onRansomPaid() {
  for (auto team : getCollective()->getTeams().getAll()) {
    vector<Creature*> members = getCollective()->getTeams().getMembers(team);
    for (Creature* c : members)
      getCollective()->cancelTask(c);
    getCollective()->getTeams().cancel(team);
  }
}
コード例 #3
0
ファイル: village_control.cpp プロジェクト: aravasio/keeperrl
void VillageControl::checkEntries() {
  if (villain)
    for (auto& trigger : villain->triggers)
      if (trigger.getId() == AttackTriggerId::ENTRY)
        for (Position pos : getCollective()->getTerritory().getAll())
          if (Creature* c = pos.getCreature())
            if (getCollective()->getTribe()->isEnemy(c))
              entries = true;
}
コード例 #4
0
void VillageControl::checkEntries() {
  for (auto& villain : villains)
    for (auto& trigger : villain.triggers)
      if (trigger.getId() == AttackTriggerId::ENTRY)
        for (Position pos : getCollective()->getTerritory().getAll())
          if (Creature* c = pos.getCreature())
            if (getCollective()->getTribe()->isEnemy(c))
              if (auto villain = getVillain(c))
                entries.insert(villain->collective);         
}
コード例 #5
0
void VillageControl::considerCancellingAttack() {
  for (auto team : getCollective()->getTeams().getAll()) {
    vector<Creature*> members = getCollective()->getTeams().getMembers(team);
    if (members.size() < (attackSizes[team] + 1) / 2 || (members.size() == 1 && members[0]->getHealth() < 0.5)) {
      for (Creature* c : members)
        getCollective()->cancelTask(c);
      getCollective()->getTeams().cancel(team);
    }
  }
}
コード例 #6
0
void VillageControl::tick(double time) {
  considerWelcomeMessage();
  considerCancellingAttack();
  checkEntries();
  vector<Creature*> allMembers = getCollective()->getCreatures();
  for (auto team : getCollective()->getTeams().getAll()) {
    for (const Creature* c : getCollective()->getTeams().getMembers(team))
      if (!getCollective()->hasTask(c)) {
        getCollective()->getTeams().cancel(team);
        break;
      }
    return;
  }
  double updateFreq = 0.1;
  if (Random.roll(1 / updateFreq))
    for (auto& villain : villains) {
      double prob = villain.getAttackProbability(this) / updateFreq;
      if (prob > 0 && Random.roll(1 / prob)) {
        vector<Creature*> fighters;
        fighters = getCollective()->getCreatures({MinionTrait::FIGHTER}, {MinionTrait::SUMMONED});
        fighters = filter(fighters, [this] (const Creature* c) {
            return contains(getCollective()->getTerritory().getAll(), c->getPosition()); });
        Debug() << getCollective()->getShortName() << " fighters: " << int(fighters.size())
          << (!getCollective()->getTeams().getAll().empty() ? " attacking " : "");
        if (fighters.size() < villain.minTeamSize || allMembers.size() < villain.minPopulation + villain.minTeamSize)
          continue;
        launchAttack(villain, getPrefix(Random.permutation(fighters),
            Random.get(villain.minTeamSize, min(fighters.size(), allMembers.size() - villain.minPopulation) + 1)));
        break;
      }
    }
}
コード例 #7
0
void VillageControl::launchAttack(Villain& villain, vector<Creature*> attackers) {
  optional<int> ransom;
  int hisGold = villain.collective->numResource(CollectiveResourceId::GOLD);
  if (villain.ransom && hisGold >= villain.ransom->second)
    ransom = max<int>(villain.ransom->second,
        (Random.getDouble(villain.ransom->first * 0.6, villain.ransom->first * 1.5)) * hisGold);
  villain.collective->addAttack(CollectiveAttack(getCollective(), attackers, ransom));
  TeamId team = getCollective()->getTeams().createPersistent(attackers);
  getCollective()->getTeams().activate(team);
  getCollective()->freeTeamMembers(team);
  for (Creature* c : attackers)
    getCollective()->setTask(c, villain.getAttackTask(this));
  attackSizes[team] = attackers.size();
}
コード例 #8
0
ファイル: village_control.cpp プロジェクト: aravasio/keeperrl
void VillageControl::onPickupEvent(const Creature* who, const vector<Item*>& items) {
  if (getCollective()->getTerritory().contains(who->getPosition()))
    if (isEnemy(who) && villain)
      if (contains(villain->triggers, AttackTriggerId::STOLEN_ITEMS)) {
        bool wasTheft = false;
        for (const Item* it : items)
          if (myItems.contains(it)) {
            wasTheft = true;
            ++stolenItemCount;
            myItems.erase(it);
          }
        if (getCollective()->hasLeader() && wasTheft) {
          who->playerMessage(PlayerMessage("You are going to regret this", MessagePriority::HIGH));
        }
    }
}
コード例 #9
0
ファイル: village_control.cpp プロジェクト: aravasio/keeperrl
void VillageControl::considerWelcomeMessage() {
  if (!getCollective()->hasLeader())
    return;
  if (villain)
    if (villain->welcomeMessage)
      switch (*villain->welcomeMessage) {
        case DRAGON_WELCOME:
          for (Position pos : getCollective()->getTerritory().getAll())
            if (Creature* c = pos.getCreature())
              if (c->isAffected(LastingEffect::INVISIBLE) && isEnemy(c) && c->isPlayer()
                  && getCollective()->getLeader()->canSee(c->getPosition())) {
                c->playerMessage(PlayerMessage("\"Well thief! I smell you and I feel your air. "
                      "I hear your breath. Come along!\"", MessagePriority::CRITICAL));
                villain->welcomeMessage.reset();
              }
          break;
      }
}
コード例 #10
0
ファイル: task.cpp プロジェクト: Nekoninja/keeperrl
 virtual MoveInfo getMove(Creature* c) override {
   CHECK(!pickedUp);
   if (c->getPosition() == getPosition()) {
     vector<Item*> hereItems;
     for (Item* it : c->getPickUpOptions())
       if (items.contains(it)) {
         hereItems.push_back(it);
         items.erase(it);
       }
     getCollective()->onCantPickItem(items);
     if (hereItems.empty()) {
       setDone();
       return NoMove;
     }
     items = hereItems;
     if (c->canPickUp(hereItems))
       return {1.0, [=] {
         for (auto elem : Item::stackItems(hereItems))
           c->globalMessage(c->getTheName() + " picks up " + elem.first, "");
         c->pickUp(hereItems);
         pickedUp = true;
         onPickedUp();
         getCollective()->onPickedUp(getPosition(), hereItems);
       }}; 
     else {
       getCollective()->onCantPickItem(items);
       setDone();
       return NoMove;
     }
   }
   if (MoveInfo move = getMoveToPosition(c, true))
     return move;
   else if (--tries == 0) {
     getCollective()->onCantPickItem(items);
     setDone();
   }
   return NoMove;
 }
コード例 #11
0
ファイル: task.cpp プロジェクト: Nekoninja/keeperrl
 virtual MoveInfo getMove(Creature* c) override {
   if (!c->hasSkill(Skill::get(SkillId::CONSTRUCTION)))
     return NoMove;
   Vec2 dir = getPosition() - c->getPosition();
   if (dir.length8() == 1) {
     if (c->canConstruct(dir, type))
       return {1.0, [this, c, dir] {
         c->construct(dir, type);
         if (!c->canConstruct(dir, type)) {
           setDone();
           getCollective()->onConstructed(getPosition(), type);
         }
       }};
     else {
       setDone();
       return NoMove;
     }
   } else
       return getMoveToPosition(c);
 }
コード例 #12
0
ファイル: village_control.cpp プロジェクト: aravasio/keeperrl
void VillageControl::launchAttack(vector<Creature*> attackers) {
  if (Collective* enemy = getEnemyCollective()) {
    for (Creature* c : attackers)
//      if (getCollective()->getGame()->canTransferCreature(c, enemy->getLevel()->getModel()))
        getCollective()->getGame()->transferCreature(c, enemy->getLevel()->getModel());
    optional<int> ransom;
    int hisGold = enemy->numResource(CollectiveResourceId::GOLD);
    if (villain->ransom && hisGold >= villain->ransom->second)
      ransom = max<int>(villain->ransom->second,
          (Random.getDouble(villain->ransom->first * 0.6, villain->ransom->first * 1.5)) * hisGold);
    enemy->addAttack(CollectiveAttack(getCollective(), attackers, ransom));
    TeamId team = getCollective()->getTeams().createPersistent(attackers);
    getCollective()->getTeams().activate(team);
    getCollective()->freeTeamMembers(team);
    for (Creature* c : attackers)
      getCollective()->setTask(c, villain->getAttackTask(this));
    attackSizes[team] = attackers.size();
  }
}
コード例 #13
0
ファイル: village_control.cpp プロジェクト: aravasio/keeperrl
void VillageControl::onOtherKilled(const Creature* victim, const Creature* killer) {
  if (victim->getTribe() == getCollective()->getTribe())
    if (isEnemy(killer))
      victims += 0.15; // small increase for same tribe but different village
}
コード例 #14
0
ファイル: village_control.cpp プロジェクト: aravasio/keeperrl
Collective* VillageControl::getEnemyCollective() const {
  return getCollective()->getGame()->getPlayerCollective();
}
コード例 #15
0
ファイル: village_control.cpp プロジェクト: aravasio/keeperrl
bool VillageControl::canPerformAttack(bool currentlyActive) {
  return !currentlyActive || getCollective()->getGame()->isSingleModel() ||
    getCollective()->getLevel()->getModel() == getCollective()->getGame()->getMainModel().get();
}