enigma-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Enigma-cvs] enigma/src actors.cc,1.44,1.45


From: Ralf Westram <address@hidden>
Subject: [Enigma-cvs] enigma/src actors.cc,1.44,1.45
Date: Tue, 21 Oct 2003 19:46:48 +0000

Update of /cvsroot/enigma/enigma/src
In directory subversions:/tmp/cvs-serv25276

Modified Files:
        actors.cc 
Log Message:
- checks for other actors when selecting a respawn destination
- FreeRespawnLocationFinder: tests all fields affected by startingpos
  [e.g. when Actor appears on the edge between two fields, both will be 
checked].
- respawn avoids some dangerous floors (water, abyss and space)
  and items (it-burnable-ignited)
- added assertions testing value returned by get_max_radius()
- const correctness for predicates



Index: actors.cc
===================================================================
RCS file: /cvsroot/enigma/enigma/src/actors.cc,v
retrieving revision 1.44
retrieving revision 1.45
diff -C2 -d -r1.44 -r1.45
*** actors.cc   20 Oct 2003 17:03:48 -0000      1.44
--- actors.cc   21 Oct 2003 19:46:46 -0000      1.45
***************
*** 47,50 ****
--- 47,54 ----
  }
  
+ double Actor::get_max_radius() {
+     return 24/64.0;
+ }
+ 
  void Actor::think(double /*dtime*/) {
      GridPos  field(actorinfo.pos);
***************
*** 67,70 ****
--- 71,75 ----
  
  namespace {
+     // helper class to find good respawn positions
  
      struct ExaminedLocation : public GridPos {
***************
*** 79,184 ****
      typedef std::set<ExaminedLocation> ExaminedLocations;
  
!     class FreeRespawnLocationFinder {
          ExaminedLocations checked;
          ExaminedLocations blocked;
          ExaminedLocations candidates;
  
!         void examine(GridPos p) {
!             if (checked.find(p) == checked.end()) {
  
!                 if (Floor *fl = GetFloor(p)) {
!                     const string& k = fl->get_kind();
!                     if (k != "fl-abyss" && k != "fl-water" && k != 
"fl-space") { // good destination floor
!                         if (Stone *st = GetStone(p)) {
!                             if (st->is_movable() || st->is_floating())
!                                 blocked.insert(p);
                          }
-                         else
-                             candidates.insert(p); // no stone -> good location
                      }
                  }
  
!                 checked.insert(p); // don't examine position multiple times
              }
          }
  
!     public:
!         FreeRespawnLocationFinder(GridPos p) {
!             blocked.insert(p);
!             checked.insert(p);
  
!             while (candidates.empty()) {
!                 ExaminedLocations curr_blocked;
!                 swap(curr_blocked, blocked);
  
!                 if (curr_blocked.empty())
!                     break; // no chance to find a candidate
  
!                 for (ExaminedLocations::const_iterator bl = 
curr_blocked.begin(); bl != curr_blocked.end(); ++bl) {
!                     examine(move(*bl, NORTH));
!                     examine(move(*bl, SOUTH));
!                     examine(move(*bl, EAST));
!                     examine(move(*bl, WEST));
!                 }
              }
  
!             if (candidates.empty())
!                 candidates.insert(p); // if no location found -> use original 
respawn position
          }
  
!         GridPos choose() const {
!             assert(!candidates.empty());
  
!             ExaminedLocations::const_iterator c = candidates.begin();
!             advance(c, IntegerRand(0, candidates.size()-1));
  
!             assert(c != candidates.end());
  
!             return *c;
!         }
  
!     };
! }
  
! void
! Actor::find_respawnpos()
! {
!     if (!use_respawnpos) {
!         GridPos non_blocking;
!         bool    non_blocking_found = false;
!         bool    blocking_found     = false;
  
!         // check all fields that may overlap with respawn position
!         for (int xoff = -1; xoff <= 1; ++xoff) {
!             for (int yoff = -1; yoff <= 1; ++yoff) {
!                 double x = startingpos[0] + xoff*.4;
!                 double y = startingpos[1] + yoff*.4;
  
!                 GridPos odest(V2(x, y));
  
!                 if (GetStone(odest) != 0) {
!                     blocking_found = true;
                  }
!                 else {
!                     non_blocking_found = true;
!                     non_blocking       = odest;
                  }
              }
          }
  
!         if (blocking_found) {
!             if (non_blocking_found) {
!                 // this only happens when the old startingpos was not
!                 // in the center of a GridPos
!                 startingpos = non_blocking.center();
!             }
!             else {
!                 GridPos                   dest(startingpos);
!                 FreeRespawnLocationFinder unblocked(dest);
!                 GridPos                   new_dest = unblocked.choose();
  
!                 startingpos = new_dest.center();
!             }
!         }
      }
  }
--- 84,307 ----
      typedef std::set<ExaminedLocation> ExaminedLocations;
  
!     class FreeRespawnLocationFinder
!     {
          ExaminedLocations checked;
          ExaminedLocations blocked;
          ExaminedLocations candidates;
  
!         const Actor &actor_to_set;
!         bool         actor_is_marble;
!         V2           preferred_position;
  
!         double max_enemy_gap;
!         V2     max_gap_pos;
! 
!         static const double MAX_DISTANCE_WANTED = 5.0;
! 
!         static bool is_marble(const string& k) {
!             // true if kind 'k' is a marble
!             return k == "ac-blackball" || k == "ac-whiteball" || k == 
"ac-whiteball-small";
!         }
! 
!         static bool is_respawn_floor(const string& k) {
!             // true if marble may appear on floors of kind 'k'
!             return
!                 k != "fl-abyss" &&
!                 k != "fl-water" &&
!                 k != "fl-space"; // player cannot be moved on fl-space
!         }
! 
!         static bool is_respawn_item(const string& k) {
!             // true if marble may appear on items of kind 'k'
!             return
!                 k != "it-laserbeam" &&
!                 k != "it-burnable-ignited";
!         }
! 
!         static bool search_through_stone(const Stone& st) {
!             if (st.is_movable() || st.is_floating()) return true;
! 
!             const string& k = st.get_kind();
!             return k == "st-puzzle";
!         }
! 
!         static double wanted_distance_to(const string& k) {
!             // returns the size of the gap wanted between a marble and an 
actor of kind 'k'
! 
!             if (k == "ac-rotor") return MAX_DISTANCE_WANTED;
!             if (k == "ac-top") return 3.0;
!             if (k == "ac-killerball" || k == "ac-bug") return 1.5;
!             return 0.3;
!         }
! 
!         double distance_wanted_to(const Actor& a) {
!             double dist = 0.3;
! 
!             if      (actor_is_marble)         dist = 
wanted_distance_to(a.get_kind());
!             else if (is_marble(a.get_kind())) dist = 
wanted_distance_to(actor_to_set.get_kind());
! 
!             assert(dist <= MAX_DISTANCE_WANTED);
!             return dist;
!         }
! 
!         bool enemyActorAt(const V2& p) {
!             vector<Actor*> found_actors;
!             double         range = actor_to_set.get_radius() + 
MAX_DISTANCE_WANTED + Actor::get_max_radius();
! 
!             if (GetActorsInRange(p, range, found_actors)) {
!                 bool   found_near_enemy = false;
!                 double min_enemy_gap    = 1000.0;
! 
!                 for (vector<Actor*>::const_iterator ai = found_actors.begin();
!                      ai != found_actors.end();
!                      ++ai)
!                 {
!                     Actor *a = *ai;
! 
!                     a->warning("  found nearby actor");
! 
!                     if (a != &actor_to_set) {
!                         double distance    = length(p - a->get_pos());
!                         double gap_between = distance - 
actor_to_set.get_radius() - a->get_radius();
!                         double wanted_gap  = distance_wanted_to(*a);
! 
!                         a->warning("  distance=%f gap_between=%f 
wanted_gap=%f", distance, gap_between, wanted_gap);
! 
!                         if (gap_between < wanted_gap)
!                             found_near_enemy = true;
! 
!                         if (gap_between < min_enemy_gap)
!                             min_enemy_gap = gap_between;
!                     }
!                 }
! 
!                 if (found_near_enemy) {
!                     if (min_enemy_gap<999.0) {
!                         if (min_enemy_gap > max_enemy_gap) {
!                             max_enemy_gap = min_enemy_gap;
!                             max_gap_pos   = p;
                          }
                      }
                  }
  
!                 return found_near_enemy;
              }
+ 
+             return false;
          }
  
!         void examine(GridPos p) {
  
!             fprintf(stderr, " examining position %i/%i\n", p.x, p.y);
  
!             if (checked.find(p) != checked.end()) return; // already examined
!             checked.insert(p);  // never check again
  
!             Floor *fl = GetFloor(p);
!             if (!fl || !is_respawn_floor(fl->get_kind())) return; // bad floor
! 
!             bool may_respawn     = true;
!             bool continue_search = true;
! 
!             Item *it = GetItem(p);
!             if (it && !is_respawn_item(it->get_kind())) may_respawn = false; 
// bad item
! 
!             Stone *st = GetStone(p);
!             if (st) {
!                 st->warning("examine");
!                 if (!search_through_stone(*st)) continue_search = false;
!                 may_respawn = false;
              }
  
!             if (may_respawn) { // may be a candidate -> check for enemy actors
!                 if (enemyActorAt(p.center())) may_respawn = false;
!             }
! 
!             fprintf(stderr, " examine result: may_respawn=%i 
continue_search=%i\n", int(may_respawn), int(continue_search));
! 
!             if (continue_search) blocked.insert(p);
!             if (may_respawn) candidates.insert(p);
          }
  
!     public:
  
!         FreeRespawnLocationFinder(V2 p, const Actor& actor)
!             : actor_to_set(actor)
!             , preferred_position(p)
!             , max_enemy_gap(-1000.0)
!         {
!             actor_is_marble = is_marble(actor_to_set.get_kind());
!             ExaminedLocations affected; // all locations affected by current 
respawn position
!             {
!                 double radius = actor_to_set.get_radius();
!                 int    xmin   = int(p[0]-radius);
!                 int    xmax   = int(p[0]+radius);
!                 int    ymin   = int(p[1]-radius);
!                 int    ymax   = int(p[1]+radius);
  
!                 for (int x = xmin; x <= xmax; ++x) {
!                     for (int y = ymin; y <= ymax; ++y) {
!                         affected.insert(GridPos(x, y));
!                     }
!                 }
!             }
  
!             fprintf(stderr, "Examining affected positions:\n");
!             for (ExaminedLocations::const_iterator ai = affected.begin(); ai 
!= affected.end(); ++ai) {
!                 examine(*ai);
!             }
!             fprintf(stderr, "Examining affected positions done.\n");
  
!             if (candidates.size() != affected.size()) { // if any affected 
location may not be used for respawning
!                 // choose alternate respawn location
  
!                 blocked = affected; // start with all affected positions
  
!                 while (candidates.empty()) {
!                     ExaminedLocations curr_blocked;
!                     swap(curr_blocked, blocked);
  
!                     if (curr_blocked.empty()) {
!                         fprintf(stderr, "No blocked locations left\n");
!                         break;  // no chance to find a candidate
!                     }
  
!                     fprintf(stderr, "Examining blocked positions:\n");
!                     for (ExaminedLocations::const_iterator bl = 
curr_blocked.begin(); bl != curr_blocked.end(); ++bl) {
!                         examine(move(*bl, NORTH));
!                         examine(move(*bl, SOUTH));
!                         examine(move(*bl, EAST));
!                         examine(move(*bl, WEST));
!                     }
!                     fprintf(stderr, "Examining blocked positions done.\n");
                  }
! 
!                 if (candidates.empty()) { // no better location -> take least 
worse tested location
!                     if (max_enemy_gap > 0.0) {
!                         fprintf(stderr, "Taking least worse position\n");
!                         preferred_position = max_gap_pos;
!                     }
!                 }
!                 else { // a better location has been found
!                     ExaminedLocations::const_iterator c = candidates.begin();
!                     advance(c, IntegerRand(0, candidates.size()-1));
! 
!                     assert(c != candidates.end());
!                     preferred_position = c->center();
!                     fprintf(stderr, "Randomly choose 1 of %i candidates\n", 
candidates.size());
                  }
              }
          }
  
!         V2 get_position() const { return preferred_position; }
!     };
! }
  
! void
! Actor::find_respawnpos()
! {
!     if (!use_respawnpos) {
!         FreeRespawnLocationFinder unblocked(startingpos, *this);
!         startingpos = unblocked.get_position();
      }
  }
***************
*** 265,270 ****
          // Actor interface.
          void think (double dtime);
!         bool is_dead() { return false; }
!         bool is_flying() { return true; }
  
        void on_hit(Actor *a) {
--- 388,393 ----
          // Actor interface.
          void think (double dtime);
!         bool is_dead() const { return false; }
!         bool is_flying() const { return true; }
  
        void on_hit(Actor *a) {
***************
*** 281,284 ****
--- 404,409 ----
      ai->mass = 0.8;
  
+     assert(ai->radius <= Actor::get_max_radius());
+ 
      set_attrib ("range", 5.0);
      set_attrib ("force", 10.0);
***************
*** 316,322 ****
              ai->radius = 12/64.0;
              ai->mass = 0.7;
          }
!         bool is_flying() { return true; }
!         bool is_dead() { return false; }
      };
  }
--- 441,449 ----
              ai->radius = 12/64.0;
              ai->mass = 0.7;
+ 
+             assert(ai->radius <= Actor::get_max_radius());
          }
!         bool is_flying() const { return true; }
!         bool is_dead() const { return false; }
      };
  }
***************
*** 335,341 ****
              ai->radius = 24/64.0;
              ai->mass = 1.2;
          }
!         bool is_flying() { return true; }
!         bool is_dead() { return false; }
      };
  }
--- 462,470 ----
              ai->radius = 24/64.0;
              ai->mass = 1.2;
+ 
+             assert(ai->radius <= Actor::get_max_radius());
          }
!         bool is_flying() const { return true; }
!         bool is_dead() const { return false; }
      };
  }
***************
*** 355,360 ****
              ai->radius = 13/64.0;
              ai->mass = 0.7;
          }
!         bool is_dead() { return false; }
  
        void on_hit(Actor *a) {
--- 484,491 ----
              ai->radius = 13/64.0;
              ai->mass = 0.7;
+ 
+             assert(ai->radius <= Actor::get_max_radius());
          }
!         bool is_dead() const { return false; }
  
        void on_hit(Actor *a) {
***************
*** 375,380 ****
          CannonBall() : Actor ("ac-cannonball", V2()) {
          }
!         bool is_flying() { return true; }
!         bool is_dead() { return false; }
      };
  }
--- 506,511 ----
          CannonBall() : Actor ("ac-cannonball", V2()) {
          }
!         bool is_flying() const { return true; }
!         bool is_dead() const { return false; }
      };
  }
***************
*** 447,456 ****
          }
  
!         bool is_dead();
!       bool is_movable() { return (state!=DEAD && state!=RESURRECTED); }
!         bool is_flying()        { return state == JUMPING; }
!         bool is_on_floor();
!         bool can_drop_items();
!         bool can_pickup_items();
          bool has_shield() const;
  
--- 578,587 ----
          }
  
!         bool is_dead() const;
!       bool is_movable() const { return (state!=DEAD && state!=RESURRECTED); }
!         bool is_flying() const { return state == JUMPING; }
!         bool is_on_floor() const;
!         bool can_drop_items() const;
!         bool can_pickup_items() const;
          bool has_shield() const;
  
***************
*** 494,500 ****
      ai->radius = radius;
      ai->mass = mass;
  }
  
! bool BasicBall::is_dead()
  {
      return state == DEAD;
--- 625,633 ----
      ai->radius = radius;
      ai->mass = mass;
+ 
+     assert(ai->radius <= Actor::get_max_radius());
  }
  
! bool BasicBall::is_dead() const
  {
      return state == DEAD;
***************
*** 502,506 ****
  
  
! bool BasicBall::is_on_floor()
  {
      return state == NORMAL || state == SINKING ||
--- 635,639 ----
  
  
! bool BasicBall::is_on_floor() const
  {
      return state == NORMAL || state == SINKING ||
***************
*** 508,512 ****
  }
  
! bool BasicBall::can_drop_items()
  {
      return state == NORMAL || state == SINKING ||
--- 641,645 ----
  }
  
! bool BasicBall::can_drop_items() const
  {
      return state == NORMAL || state == SINKING ||
***************
*** 514,518 ****
  }
  
! bool BasicBall::can_pickup_items()
  {
      return state == NORMAL || state == SINKING || state == JUMP_VORTEX;
--- 647,651 ----
  }
  
! bool BasicBall::can_pickup_items() const
  {
      return state == NORMAL || state == SINKING || state == JUMP_VORTEX;





reply via email to

[Prev in Thread] Current Thread [Next in Thread]