/[enigma]/enigma/src/stones_complex.cc
ViewVC logotype

Diff of /enigma/src/stones_complex.cc

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.25 by reallysoft, Fri Jun 27 08:02:12 2003 UTC revision 1.26 by reallysoft, Mon Jun 30 08:48:11 2003 UTC
# Line 789  member of a cluster or not). Line 789  member of a cluster or not).
789     or columnwise. Groups of oxyd-compatible puzzle stones are shuffled     or columnwise. Groups of oxyd-compatible puzzle stones are shuffled
790     randomly at level startup.     randomly at level startup.
791    
   
792  \subsection puzzlee Example  \subsection puzzlee Example
793  <table>  <table>
794  <tr>  <tr>
# Line 817  member of a cluster or not). Line 816  member of a cluster or not).
816  */  */
817  namespace  namespace
818  {  {
819      class PuzzleStone : public ConnectiveStone, public TimeHandler {      class PuzzleStone : public ConnectiveStone, public TimeHandler, public laser::PhotoCell {
820          INSTANCELISTOBJ(PuzzleStone);          INSTANCELISTOBJ(PuzzleStone);
821      public:      public:
822          PuzzleStone(int connections, bool oxyd1_compatible_)          PuzzleStone(int connections, bool oxyd1_compatible_)
823              : ConnectiveStone("st-puzzle", connections)              : ConnectiveStone("st-puzzle", connections)
824              , state(IDLE)              , state(IDLE)
825                , illumination(NODIRBIT)
826          {          {
827              set_attrib("oxyd", int(oxyd1_compatible_));              set_attrib("oxyd", int(oxyd1_compatible_));
828          }          }
# Line 842  namespace Line 842  namespace
842                                          Direction  dir, int wanted_oxyd_attrib);                                          Direction  dir, int wanted_oxyd_attrib);
843    
844          bool cluster_complete();          bool cluster_complete();
845          void maybe_move_cluster(Cluster &c, bool is_complete, Direction dir);          void maybe_move_cluster(Cluster &c, bool is_complete, bool actor_with_wand, Direction dir);
846          void rotate_cluster(const Cluster &c);          void rotate_cluster(const Cluster &c);
847            void maybe_rotate_cluster(Direction dir);
848    
849          void shuffle(int count);          void shuffle(int count);
850    
851          void message(const string& msg, const Value &val);          void message(const string& msg, const Value &val);
852    
853            void on_creation();
854            void on_removal();
855    
856          bool on_laserhit(Direction);          bool on_laserhit(Direction);
857          void on_impulse(const Impulse& impulse);          void on_impulse(const Impulse& impulse);
858    
# Line 868  namespace Line 872  namespace
872    
873          void alarm();          void alarm();
874    
875            // PhotoCell interface.
876            void on_recalc_start();
877            void on_recalc_finish();
878    
879            DirectionBits calc_illumination();
880    
881          // Variables          // Variables
882          bool visited;           // flag for DFS          bool visited;           // flag for DFS
   
883          enum { IDLE, EXPLODING } state;          enum { IDLE, EXPLODING } state;
884            DirectionBits illumination; // last state of surrounding laser beams
885      };      };
886  }  }
887    
# Line 1001  PuzzleStone::find_row_or_column_cluster( Line 1011  PuzzleStone::find_row_or_column_cluster(
1011  }  }
1012    
1013  void  void
1014  PuzzleStone::maybe_move_cluster(Cluster &c, bool is_complete, Direction dir)  PuzzleStone::maybe_move_cluster(Cluster &c, bool is_complete, bool actor_with_wand, Direction dir)
1015  {  {
1016      sort(c.begin(), c.end());      sort(c.begin(), c.end());
1017      Cluster mc(c);              // Moved cluster      Cluster mc(c);              // Moved cluster
# Line 1023  PuzzleStone::maybe_move_cluster(Cluster Line 1033  PuzzleStone::maybe_move_cluster(Cluster
1033      if (!move_ok)      if (!move_ok)
1034          return;          return;
1035    
1036      // If the floor at the cluster's new position consists exclusively      // If the floor at a complete cluster's new position consists
1037      // of abyss or water, create a bridge instead of moving the      // exclusively of abyss or water, create a bridge instead of
1038      // cluster.      // moving the cluster.
1039      bool create_bridge = false;      //
1040        // For partial clusters build bridges only on water and if
1041      if (is_complete) {      // the wielded item is not the magic wand.
1042          create_bridge = true;  
1043          for (unsigned i=0; i<mc.size(); ++i) {      bool create_bridge = true;
1044              if (Floor *fl = GetFloor(mc[i])) {  
1045                  if (!fl->is_kind("fl-abyss") && !fl->is_kind("fl-water")) {      for (unsigned i=0; create_bridge && i<mc.size(); ++i) {
1046                      create_bridge = false;          if (Floor *fl = GetFloor(mc[i])) {
1047                      break;              if (fl->is_kind("fl-abyss")) {
1048                  }                  if (!is_complete) create_bridge = false;
1049                }
1050                else if (fl->is_kind("fl-water")) {
1051                    if (!is_complete && actor_with_wand) create_bridge = false;
1052                }
1053                else {
1054                    create_bridge = false;
1055              }              }
1056          }          }
1057      }      }
# Line 1100  PuzzleStone::collision_response(const St Line 1116  PuzzleStone::collision_response(const St
1116  void  void
1117  PuzzleStone::shuffle(int count)  PuzzleStone::shuffle(int count)
1118  {  {
1119      if (oxyd1_compatible()) {      assert(oxyd1_compatible());
1120          Direction move_dir = static_cast<Direction>(IntegerRand(0, 3));  
1121          Cluster   c;      Direction move_dir = static_cast<Direction>(IntegerRand(0, 3));
1122          find_row_or_column_cluster(c, get_pos(), reverse(move_dir), 1);      Cluster   c;
1123          if (!c.empty()) {      find_row_or_column_cluster(c, get_pos(), reverse(move_dir), 1);
1124              GridPos last = c.back();      if (!c.empty()) {
1125            GridPos last = c.back();
1126            c.clear();
1127            find_row_or_column_cluster(c, last, move_dir, 1);
1128    
1129            // if cluster too small to rotate -> turn direction by 90 deg
1130            if (c.size() <= 1) {
1131                move_dir = rotate(move_dir, true);
1132              c.clear();              c.clear();
1133              find_row_or_column_cluster(c, last, move_dir, 1);              find_row_or_column_cluster(c, last, move_dir, 1);
1134            }
1135    
1136              // if cluster too small to rotate -> turn direction by 90 deg          if (c.size() > 1) {
             if (c.size() <= 1) {  
                 move_dir = rotate(move_dir, true);  
                 c.clear();  
                 find_row_or_column_cluster(c, last, move_dir, 1);  
             }  
   
             if (c.size() > 1) {  
1137    
1138                  // @@@ FIXME:  check whether rotation is impossible              // @@@ FIXME:  check whether rotation is impossible
1139                  // (e.g. blocked by unmoveable stone at both sides)              // (e.g. blocked by unmoveable stone at both sides)
1140    
1141                  while (count--)              while (count--)
1142                      rotate_cluster(c);                  rotate_cluster(c);
             }  
1143          }          }
1144      }      }
1145  }  }
# Line 1165  PuzzleStone::explode() { Line 1181  PuzzleStone::explode() {
1181    
1182      // @@@ FIXME: At the moment it's possible to push partial puzzle stones      // @@@ FIXME: At the moment it's possible to push partial puzzle stones
1183      // next to an already exploding cluster. Then the part will explode as well.      // next to an already exploding cluster. Then the part will explode as well.
1184      // I've no idea what oxyd does, but to fix this we have to change the way      // Possible fix : mark whole cluster as "EXPLODING_SOON" when explosion is initiated
     // how explosions are forwarded. [ralf]  
1185    
1186      // ignite adjacent fields      // ignite adjacent fields
1187      SendExplosionEffect(p, DYNAMITE);      SendExplosionEffect(p, DYNAMITE);
# Line 1178  PuzzleStone::alarm() { Line 1193  PuzzleStone::alarm() {
1193  }  }
1194    
1195  void  void
1196  PuzzleStone::message(const string& msg, const Value &) {  PuzzleStone::message(const string& msg, const Value &val) {
1197      if (msg == "init") {        // shuffle at level startup      if (oxyd1_compatible()) {
1198          int count = options::Difficulty == DIFFICULTY_EASY          if (msg == "init") {
1199              ? 1              // shuffle oxyd1 style puzzle pieces at level startup.
1200              : IntegerRand(0, 4);              // only done this way if gametype is GAMET_ENIGMA.
1201                if (enigma::GameCompatibility == GAMET_ENIGMA) {
1202                    int count = options::Difficulty == DIFFICULTY_EASY
1203                        ? 1
1204                        : IntegerRand(0, 4);
1205    
1206          shuffle(count);                  shuffle(count);
1207                }
1208            }
1209            else if (msg == "scramble") {
1210                // oxyd levels contain explicit information on how to
1211                // shuffle puzzle stones. According to that information
1212                // a "scramble" message is send to specific puzzle stones
1213                // together with information about the direction.
1214                // only done this way if gametype is not GAMET_ENIGMA.
1215    
1216                Direction dir = static_cast<Direction>(val.get_double());
1217                Cluster   c;
1218                find_row_or_column_cluster(c, get_pos(), dir, 1);
1219    
1220                int size = c.size();
1221                if (size >= 2) {
1222                    int count = IntegerRand(1, size-1);
1223                    while (count--)
1224                        rotate_cluster(c);
1225                }
1226            }
1227      }      }
1228  }  }
1229    
# Line 1193  PuzzleStone::on_impulse(const Impulse& i Line 1232  PuzzleStone::on_impulse(const Impulse& i
1232  {  {
1233      if (!oxyd1_compatible() && state == IDLE) {      if (!oxyd1_compatible() && state == IDLE) {
1234          Cluster c;          Cluster c;
1235          bool    is_complete = find_cluster(c);          bool    is_complete     = find_cluster(c);
1236          maybe_move_cluster(c, is_complete, impulse.dir);          bool    actor_with_wand = false;
1237    
1238            if (Actor *ac = dynamic_cast<Actor*>(impulse.sender)) {
1239                actor_with_wand = wielded_item_is(ac, "it-magicwand");
1240            }
1241    
1242            maybe_move_cluster(c, is_complete, actor_with_wand, impulse.dir);
1243      }      }
1244  }  }
1245    
1246  bool  bool
1247  PuzzleStone::explode_complete_cluster()  PuzzleStone::explode_complete_cluster()
1248  {  {
1249        // @@@ FIXME: explode_complete_cluster should mark the whole cluster
1250        // as "EXPLODING_SOON" (otherwise it may be changed before it explodes completely)
1251    
1252      assert(state == IDLE);      assert(state == IDLE);
1253      bool exploded = false;      bool exploded = false;
1254    
# Line 1251  PuzzleStone::explode_complete_cluster() Line 1299  PuzzleStone::explode_complete_cluster()
1299                  }                  }
1300    
1301                  if (exploded) {                  if (exploded) {
1302                        warning("exploding complete cluster");
1303                      explode();                      explode();
1304                  }                  }
1305              }              }
# Line 1261  PuzzleStone::explode_complete_cluster() Line 1310  PuzzleStone::explode_complete_cluster()
1310  }  }
1311    
1312  bool  bool
1313  PuzzleStone::on_laserhit(Direction)  PuzzleStone::on_laserhit(Direction )
1314  {  {
     if (state == IDLE && explode_complete_cluster())  
         return false;  
   
1315      return get_connections() == 0;      return get_connections() == 0;
1316  }  }
1317    
1318  void  void
1319    PuzzleStone::maybe_rotate_cluster(Direction dir)
1320    {
1321        assert(oxyd1_compatible());
1322        warning("maybe_rotate_cluster dir=%i", int(dir));
1323    
1324        Cluster c;
1325        find_row_or_column_cluster(c, get_pos(), dir, 1);
1326        if (c.size() >= 2) {
1327            warning("ok -> rotate");
1328            rotate_cluster(c);
1329        }
1330    }
1331    
1332    void PuzzleStone::on_creation()
1333    {
1334        photo_activate();
1335        ConnectiveStone::on_creation();
1336        illumination = DirectionBits(ALL_DIRECTIONS+1); // invalid
1337    }
1338    
1339    void PuzzleStone::on_removal()
1340    {
1341        photo_deactivate();
1342        ConnectiveStone::on_removal();
1343    }
1344    
1345    void
1346    PuzzleStone::on_recalc_start()
1347    {
1348    }
1349    
1350    DirectionBits
1351    PuzzleStone::calc_illumination()
1352    {
1353        DirectionBits illu = NODIRBIT;
1354        GridPos       p    = get_pos();
1355    
1356        if (laser::LightFrom(p, NORTH)) illu = DirectionBits(illu|NORTHBIT);
1357        if (laser::LightFrom(p, SOUTH)) illu = DirectionBits(illu|SOUTHBIT);
1358        if (laser::LightFrom(p, EAST))  illu = DirectionBits(illu|EASTBIT);
1359        if (laser::LightFrom(p, WEST))  illu = DirectionBits(illu|WESTBIT);
1360    
1361        return illu;
1362    }
1363    
1364    void
1365    PuzzleStone::on_recalc_finish()
1366    {
1367        DirectionBits illu = calc_illumination();
1368    
1369        if (illu != illumination) {
1370            if (illumination == (ALL_DIRECTIONS+1)) {
1371                warning("initializing illumination on new stone");
1372            }
1373            else {
1374                warning("illumination changed (old=%i new=%i)", illumination, illu);
1375    
1376                DirectionBits newBeams = DirectionBits(illu ^ (illu & illumination));
1377    
1378                if (state == IDLE && newBeams != NODIRBIT) {
1379                    if (!explode_complete_cluster()) {
1380                        if (oxyd1_compatible()) {
1381                            if (newBeams & NORTHBIT) maybe_rotate_cluster(SOUTH);
1382                            if (newBeams & SOUTHBIT) maybe_rotate_cluster(NORTH);
1383                            if (newBeams & EASTBIT)  maybe_rotate_cluster(WEST);
1384                            if (newBeams & WESTBIT)  maybe_rotate_cluster(EAST);
1385                        }
1386                    }
1387                }
1388            }
1389            illumination = illu;
1390        }
1391    }
1392    
1393    
1394    void
1395  PuzzleStone::actor_hit(const StoneContact &sc)  PuzzleStone::actor_hit(const StoneContact &sc)
1396  {  {
1397      if (get_connections() == NODIRBIT)      if (get_connections() == NODIRBIT)

Legend:
Removed from v.1.25  
changed lines
  Added in v.1.26

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26