Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ai/src/orxonox/controllers/ArtificialController.cc @ 6852

Last change on this file since 6852 was 6850, checked in by solex, 15 years ago

master/slave interaction of bots now correct - getting closer to formation flight

  • Property svn:eol-style set to native
File size: 15.3 KB
RevLine 
[2362]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "ArtificialController.h"
30
31#include "core/CoreIncludes.h"
[6601]32#include "core/XMLPort.h"
[5735]33#include "worldentities/ControllableEntity.h"
34#include "worldentities/pawns/Pawn.h"
35#include "worldentities/pawns/TeamBaseMatchBase.h"
36#include "gametypes/TeamDeathmatch.h"
37#include "controllers/WaypointPatrolController.h"
[3049]38
[2362]39namespace orxonox
40{
41    ArtificialController::ArtificialController(BaseObject* creator) : Controller(creator)
42    {
43        RegisterObject(ArtificialController);
44
45        this->target_ = 0;
[6695]46        this->myMaster_ = 0;
[6850]47        this->freedomCount_ = 0;
48        this->team_ = -1;
49        this->state_ = FREE;
[2362]50        this->bShooting_ = false;
51        this->bHasTargetPosition_ = false;
52        this->targetPosition_ = Vector3::ZERO;
[6417]53
[5929]54        this->target_.setCallback(createFunctor(&ArtificialController::targetDied, this));
[2362]55    }
56
57    ArtificialController::~ArtificialController()
58    {
59    }
60
[6601]61    void ArtificialController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
62    {
63        SUPER(ArtificialController, XMLPort, xmlelement, mode);
64
65        XMLPortParam(ArtificialController, "team", setTeam, getTeam, xmlelement, mode).defaultValues(0);
66    }
67
[6850]68// gets called when Bot dies
69    void ArtificialController::changedControllableEntity()
70    {
71COUT(0) << "~changedControllableEntity 0" << std::endl;
72        if(!getControllableEntity()) 
73        {
74COUT(0) << "~changedControllableEntity 1" << std::endl;
75        if (this->state_ == SLAVE) unregisterSlave();
76COUT(0) << "~changedControllableEntity 2" << std::endl;
77         if (this->state_ == MASTER) setNewMasterWithinFormation();
78COUT(0) << "~changedControllableEntity 3" << std::endl;
79        this->slaves_.clear();
80COUT(0) << "~changedControllableEntity 4" << std::endl;
81        this->state_ = FREE;
82COUT(0) << "~changedControllableEntity 5" << std::endl;
83        }
84    }
85
[3049]86    void ArtificialController::moveToPosition(const Vector3& target)
[2362]87    {
88        if (!this->getControllableEntity())
89            return;
90
[3049]91        Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, target);
92        float distance = (target - this->getControllableEntity()->getPosition()).length();
[2362]93
[2493]94        if (this->target_ || distance > 10)
[2362]95        {
[6850]96            // Multiply with rotateFactor to make them a bit slower
97            float rotateFactor;
98            if(this->state_ == SLAVE) rotateFactor = 1.0f;
99            if(this->state_ == MASTER) rotateFactor = 0.4f;
100            else rotateFactor = 0.8f;
101
102            this->getControllableEntity()->rotateYaw(-1.0f * rotateFactor * sgn(coord.x) * coord.x*coord.x);
103            this->getControllableEntity()->rotatePitch(rotateFactor * sgn(coord.y) * coord.y*coord.y);
104
105
106
[2362]107        }
108
[2493]109        if (this->target_ && distance < 200 && this->getControllableEntity()->getVelocity().squaredLength() > this->target_->getVelocity().squaredLength())
[6850]110        {
111            if(this->state_ == SLAVE) this->getControllableEntity()->moveFrontBack(-0.8f);
112            else this->getControllableEntity()->moveFrontBack(-0.05f); // They don't brake with full power to give the player a chance
113        } else {
114            if(this->state_ == SLAVE) this->getControllableEntity()->moveFrontBack(2.5f);
115            if(this->state_ == MASTER) this->getControllableEntity()->moveFrontBack(0.4f);
116            else this->getControllableEntity()->moveFrontBack(0.8f);
117        }
[2362]118    }
119
[3049]120    void ArtificialController::moveToTargetPosition()
121    {
122        this->moveToPosition(this->targetPosition_);
123    }
124
[6640]125    int ArtificialController::getState()
126    {
127        return this->state_;
128    }
129
[6695]130    void ArtificialController::unregisterSlave() {
131        if(myMaster_)
132        {
[6795]133            myMaster_->slaves_.remove(this);
[6850]134COUT(0) << "~unregister slave" << std::endl;
[6695]135        }
136    }
137
[6640]138    void ArtificialController::searchNewMaster()
139    {
[6695]140
[6640]141        if (!this->getControllableEntity())
142            return;
143
144        this->targetPosition_ = this->getControllableEntity()->getPosition();
145        this->forgetTarget();
146
147        //go through all pawns
148        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
149        {
[6695]150
151            //same team?
[6640]152            if (!ArtificialController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))
153                continue;
154
[6695]155            //has it an ArtificialController and is it a master?
156            if (!it->getController())
157                continue;
[6640]158
[6850]159            ArtificialController *newMaster = static_cast<ArtificialController*>(it->getController());
160
161            if (!newMaster || newMaster->getState() != MASTER)
[6640]162                continue;
163
164            //is pawn oneself? && is pawn in range?
[6695]165            if (static_cast<ControllableEntity*>(*it) != this->getControllableEntity()) //&& it->getPosition().squaredDistance(this->getControllableEntity()->getPosition()) < 1000
[6640]166            {
[6850]167                if(newMaster->slaves_.size() > 6) continue;
[6696]168
[6850]169                //this->freeSlaves();
170
171                for(std::list<ArtificialController*>::iterator itSlave = this->slaves_.begin(); itSlave != this->slaves_.end(); itSlave++)
172                {
173                    (*itSlave)->myMaster_ = newMaster;
174                    newMaster->slaves_.push_back(*itSlave);
175                }
[6795]176                this->slaves_.clear();
[6683]177                this->state_ = SLAVE;
[6696]178
[6850]179                this->myMaster_ = newMaster;
180                newMaster->slaves_.push_back(this);
[6696]181
[6695]182                break;
[6640]183            }
184        }//for
185
186        //hasn't encountered any masters in range? -> become a master
[6695]187        if (state_!=SLAVE) state_ = MASTER; // keep in mind: what happens when two masters encounter eache other? -> has to be evaluated in the for loop within master mode in AIcontroller...
[6850]188COUT(0) << "~searcheNewMaster" << std::endl;
[6640]189    }
190
[6683]191    void ArtificialController::commandSlaves() {
192
[6795]193        for(std::list<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
[6695]194        {
195            (*it)->setTargetPosition(this->getControllableEntity()->getPosition());
196        }
[6683]197    }
198
[6795]199    // binds slaves to new Master within formation
200    void ArtificialController::setNewMasterWithinFormation()
201    {
202COUT(0) << "~setNewMasterWithinFormation 1" << std::endl;
203        if (this->slaves_.empty())
204            return;
205COUT(0) << "~setNewMasterWithinFormation 1b" << std::endl;
206
207        ArtificialController *newMaster = this->slaves_.back();
208COUT(0) << "~setNewMasterWithinFormation 2" << std::endl;
209        this->slaves_.pop_back();
210COUT(0) << "~setNewMasterWithinFormation 3" << std::endl;
211        if(!newMaster) return;
212COUT(0) << "~setNewMasterWithinFormation 4" << std::endl;
213        newMaster->state_ = MASTER;
214        newMaster->slaves_ = this->slaves_;
[6850]215        this->slaves_.clear();
[6795]216
217        this->state_ = SLAVE;
218        this->myMaster_ = newMaster;
219
220COUT(0) << "~setNewMasterWithinFormation 5" << std::endl;
221        for(std::list<ArtificialController*>::iterator it = newMaster->slaves_.begin(); it != newMaster->slaves_.end(); it++)
222        {
223COUT(0) << "~setNewMasterWithinFormation 6" << std::endl;
224            (*it)->myMaster_ = newMaster;
225        }
226COUT(0) << "~setNewMasterWithinFormation 7" << std::endl;
227
228    }
229
[6850]230    void ArtificialController::freeSlaves()
[6683]231    {
[6795]232        for(std::list<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
[6696]233        {
234            (*it)->state_ = FREE;
235        }
[6850]236        this->slaves_.clear();
237    }
238
239    void ArtificialController::forceFreeSlaves()
240    {
241        for(std::list<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
[6683]242        {
[6850]243            (*it)->state_ = FREE;
244            (*it)->forceFreedom();
245            (*it)->targetPosition_ = this->targetPosition_;
246            (*it)->bShooting_ = true;
247            (*it)->getControllableEntity()->fire(0);
[6683]248        }
[6696]249    }
[6683]250
[6696]251    void ArtificialController::loseMasterState()
252    {
[6850]253        this->freeSlaves();
[6696]254        this->state_ = FREE;
[6683]255    }
256
[6850]257    void ArtificialController::forceFreedom()
258    {
259        this->freedomCount_ = 5;
260    }
261
262    bool ArtificialController::forcedFree()
263    {
264        if(this->freedomCount_ > 0) 
265        {
266            this->freedomCount_--;
267            return true;
268        } else return false;
269    }
270
[3049]271    void ArtificialController::setTargetPosition(const Vector3& target)
272    {
273        this->targetPosition_ = target;
274        this->bHasTargetPosition_ = true;
275    }
276
[2362]277    void ArtificialController::searchRandomTargetPosition()
278    {
[2493]279        this->targetPosition_ = Vector3(rnd(-2000,2000), rnd(-2000,2000), rnd(-2000,2000));
[2362]280        this->bHasTargetPosition_ = true;
281    }
282
[3049]283    void ArtificialController::setTarget(Pawn* target)
284    {
285        this->target_ = target;
286
287        if (target)
288            this->targetPosition_ = target->getPosition();
289    }
290
[2362]291    void ArtificialController::searchNewTarget()
292    {
293        if (!this->getControllableEntity())
294            return;
295
296        this->targetPosition_ = this->getControllableEntity()->getPosition();
297        this->forgetTarget();
298
299        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
300        {
[3049]301            if (ArtificialController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))
302                continue;
303
[2506]304            if (static_cast<ControllableEntity*>(*it) != this->getControllableEntity())
[2362]305            {
306                float speed = this->getControllableEntity()->getVelocity().length();
307                Vector3 distanceCurrent = this->targetPosition_ - this->getControllableEntity()->getPosition();
308                Vector3 distanceNew = it->getPosition() - this->getControllableEntity()->getPosition();
309                if (!this->target_ || it->getPosition().squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceNew) / speed / distanceNew.length()) / (2 * Ogre::Math::PI))
310                        < this->targetPosition_.squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceCurrent) / speed / distanceCurrent.length()) / (2 * Ogre::Math::PI)) + rnd(-250, 250))
311                {
312                    this->target_ = (*it);
313                    this->targetPosition_ = it->getPosition();
314                }
315            }
316        }
317    }
318
319    void ArtificialController::forgetTarget()
320    {
321        this->target_ = 0;
322        this->bShooting_ = false;
323    }
324
325    void ArtificialController::aimAtTarget()
326    {
327        if (!this->target_ || !this->getControllableEntity())
328            return;
329
[2493]330        static const float hardcoded_projectile_speed = 1250;
[2362]331
[2493]332        this->targetPosition_ = getPredictedPosition(this->getControllableEntity()->getPosition(), hardcoded_projectile_speed, this->target_->getPosition(), this->target_->getVelocity());
[2362]333        this->bHasTargetPosition_ = (this->targetPosition_ != Vector3::ZERO);
[6417]334
335        Pawn* pawn = dynamic_cast<Pawn*>(this->getControllableEntity());
336        if (pawn)
337            pawn->setAimPosition(this->targetPosition_);
[2362]338    }
339
340    bool ArtificialController::isCloseAtTarget(float distance) const
341    {
342        if (!this->getControllableEntity())
343            return false;
344
345        if (!this->target_)
346            return (this->getControllableEntity()->getPosition().squaredDistance(this->targetPosition_) < distance*distance);
347        else
348            return (this->getControllableEntity()->getPosition().squaredDistance(this->target_->getPosition()) < distance*distance);
349    }
350
351    bool ArtificialController::isLookingAtTarget(float angle) const
352    {
353        if (!this->getControllableEntity())
354            return false;
355
356        return (getAngle(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->targetPosition_) < angle);
357    }
358
[5929]359    void ArtificialController::abandonTarget(Pawn* target)
[2362]360    {
[5929]361        if (target == this->target_)
362            this->targetDied();
[2362]363    }
[3049]364
[5929]365    void ArtificialController::targetDied()
366    {
367        this->forgetTarget();
368        this->searchRandomTargetPosition();
369    }
370
[3049]371    bool ArtificialController::sameTeam(ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
372    {
373        if (entity1 == entity2)
374            return true;
375
376        int team1 = -1;
377        int team2 = -1;
378
[6601]379        Controller* controller = 0;
380        if (entity1->getController())
381            controller = entity1->getController();
382        else
383            controller = entity1->getXMLController();
384        if (controller)
[3049]385        {
[6601]386            ArtificialController* ac = orxonox_cast<ArtificialController*>(controller);
387            if (ac)
388                team1 = ac->getTeam();
[3049]389        }
[6601]390
391        if (entity1->getController())
392            controller = entity1->getController();
393        else
394            controller = entity1->getXMLController();
395        if (controller)
[3049]396        {
[6601]397            ArtificialController* ac = orxonox_cast<ArtificialController*>(controller);
398            if (ac)
399                team2 = ac->getTeam();
[3049]400        }
401
[3325]402        TeamDeathmatch* tdm = orxonox_cast<TeamDeathmatch*>(gametype);
[3049]403        if (tdm)
404        {
405            if (entity1->getPlayer())
406                team1 = tdm->getTeam(entity1->getPlayer());
407
408            if (entity2->getPlayer())
409                team2 = tdm->getTeam(entity2->getPlayer());
410        }
411
[3086]412        TeamBaseMatchBase* base = 0;
[3325]413        base = orxonox_cast<TeamBaseMatchBase*>(entity1);
[3086]414        if (base)
415        {
416            switch (base->getState())
417            {
[3280]418                case BaseState::ControlTeam1:
[3086]419                    team1 = 0;
420                    break;
[3280]421                case BaseState::ControlTeam2:
[3086]422                    team1 = 1;
423                    break;
[3280]424                case BaseState::Uncontrolled:
[3086]425                default:
426                    team1 = -1;
427            }
428        }
[3325]429        base = orxonox_cast<TeamBaseMatchBase*>(entity2);
[3086]430        if (base)
431        {
432            switch (base->getState())
433            {
[3280]434                case BaseState::ControlTeam1:
[3086]435                    team2 = 0;
436                    break;
[3280]437                case BaseState::ControlTeam2:
[3086]438                    team2 = 1;
439                    break;
[3280]440                case BaseState::Uncontrolled:
[3086]441                default:
442                    team2 = -1;
443            }
444        }
445
[3049]446        return (team1 == team2 && team1 != -1);
447    }
[2362]448}
Note: See TracBrowser for help on using the repository browser.