/[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.10 by dheck, Thu Jun 12 11:04:23 2003 UTC revision 1.11 by reallysoft, Mon Jun 16 18:39:33 2003 UTC
# Line 472  namespace Line 472  namespace
472              if (Stone *st = GetStone(move(get_pos(), dir))) {              if (Stone *st = GetStone(move(get_pos(), dir))) {
473                  if (state == ACTIVE) { // allowed to trigger?                  if (state == ACTIVE) { // allowed to trigger?
474                      state = IDLE;                      state = IDLE;
475                      if (st->is_kind("st-pull")) {  
476                          send_impulse(st->get_pos(), dir);  //                     if (st->is_kind("st-pull")) {
477                      }  //                         send_impulse(st->get_pos(), dir);
478                      else {  //                     }
479                          SendMessage(st, "trigger", Value(dir));  //                     else {
480                      }                      SendMessage(st, "trigger", Value(dir));
481    //                     }
482                  }                  }
483                  return true;                  return true;
484              }              }
# Line 656  A cluster of puzzle stones may for examp Line 657  A cluster of puzzle stones may for examp
657    
658  This example actually presents the special case of a ``complete''  This example actually presents the special case of a ``complete''
659  cluster.  A cluster is complete if none of its stones has an  cluster.  A cluster is complete if none of its stones has an
660  unconnected socket.  If such a group is touched with a magic wand, all  unconnected socket.
661  its constituents explode.  [They should, anyway. This is not  
662  implemented yet.]  When touched with a magic wand the puzzle stones rotate
663    row- or columnwise. If one of these rows/columns contains exactly
664    one stone, then that stone is moved (regardless whether it is a
665    member of a cluster or not).
666    
667  \subsection puzzlea Attributes  \subsection puzzlea Attributes
668    
# Line 667  implemented yet.] Line 671  implemented yet.]
671     a socket on one of the four faces.  You will normally simply use     a socket on one of the four faces.  You will normally simply use
672     one of the Lua constants \c PUZ_0000 to \c PUZ_1111.     one of the Lua constants \c PUZ_0000 to \c PUZ_1111.
673    
674    - \b oxyd
675       If 1 then the puzzle stones act oxyd-compatible: Complete clusters
676       explode, when they get touched. All other puzzle stones rotate row-
677       or columnwise. Groups of oxyd-compatible puzzle stones are shuffled
678       randomly at level startup.
679    
680    
681  \subsection puzzlee Example  \subsection puzzlee Example
682  <table>  <table>
683  <tr>  <tr>
# Line 697  namespace Line 708  namespace
708      class PuzzleStone : public Stone {      class PuzzleStone : public Stone {
709          INSTANCELISTOBJ(PuzzleStone);          INSTANCELISTOBJ(PuzzleStone);
710      public:      public:
711          PuzzleStone(int connections=0) : Stone("st-puzzle") {          PuzzleStone(int connections, bool oxyd1_compatible_)
712                : Stone("st-puzzle")
713            {
714              set_attrib("connections", connections);              set_attrib("connections", connections);
715                set_attrib("oxyd", int(oxyd1_compatible_));
716          }          }
717      private:      private:
718          typedef vector<GridPos> Cluster;          typedef vector<GridPos> Cluster;
719    
720          DirectionBits get_connections();          DirectionBits get_connections();
721            bool oxyd1_compatible() const { return int_attrib("oxyd") != 0; }
722    
723          static bool visit_dir(vector<GridPos> &stack,          static bool visit_dir(vector<GridPos> &stack,
724                                GridPos curpos, Direction dir);                                GridPos curpos, Direction dir);
# Line 714  namespace Line 729  namespace
729          void maybe_move_cluster(Cluster &c, bool is_complete, Direction dir);          void maybe_move_cluster(Cluster &c, bool is_complete, Direction dir);
730          void rotate_cluster(const Cluster &c);          void rotate_cluster(const Cluster &c);
731    
732            void shuffle(int count);
733    
734            void message(const string& msg, const Value &val);
735    
736          bool on_laserhit(Direction /*dir*/) {          bool on_laserhit(Direction /*dir*/) {
737              return get_connections() == 0;              return get_connections() == 0;
738          }          }
# Line 811  PuzzleStone::find_cluster(Cluster &clust Line 830  PuzzleStone::find_cluster(Cluster &clust
830  void  void
831  PuzzleStone::find_row_or_column_cluster(Cluster &c, GridPos startpos, Direction dir)  PuzzleStone::find_row_or_column_cluster(Cluster &c, GridPos startpos, Direction dir)
832  {  {
833        assert(dir != NODIR);
834    
835      GridPos p = startpos;      GridPos p = startpos;
836      while (dynamic_cast<PuzzleStone*>(GetStone(p))) {      while (dynamic_cast<PuzzleStone*>(GetStone(p))) {
837          c.push_back(p);          c.push_back(p);
# Line 892  PuzzleStone::init_model() Line 913  PuzzleStone::init_model()
913    
914      // Every combination of ``sockets'' has its own model.      // Every combination of ``sockets'' has its own model.
915      int modelno = int_attrib("connections");      int modelno = int_attrib("connections");
916        if (oxyd1_compatible()) modelno += 16;
917      sprintf(x, "%d", modelno);      sprintf(x, "%d", modelno);
918      modelname += x;      modelname += x;
919      set_model(modelname);      set_model(modelname);
# Line 921  PuzzleStone::collision_response(const St Line 943  PuzzleStone::collision_response(const St
943  }  }
944    
945  void  void
946    PuzzleStone::shuffle(int count)
947    {
948        if (oxyd1_compatible()) {
949            Direction move_dir = Direction(4*(rand()/(RAND_MAX+1.0)));
950            Cluster   c;
951            find_row_or_column_cluster(c, get_pos(), reverse(move_dir));
952            if (!c.empty()) {
953                GridPos last = c.back();
954                c.clear();
955                find_row_or_column_cluster(c, last, move_dir);
956    
957                // if cluster too small to rotate -> turn direction by 90 deg
958                if (c.size() <= 1) {
959                    move_dir = rotate(move_dir, true);
960                    c.clear();
961                    find_row_or_column_cluster(c, last, move_dir);
962                }
963    
964                if (c.size() > 1) {
965    
966                    // @@@ FIXME:  check whether rotation is impossible
967                    // (e.g. blocked by unmoveable stone at both sides)
968    
969                    while (count--)
970                        rotate_cluster(c);
971                }
972            }
973        }
974    }
975    
976    void PuzzleStone::message(const string& msg, const Value &) {
977        if (msg == "init") {        // shuffle at level startup
978            int count = options::Difficulty == DIFFICULTY_EASY
979                ? 1
980                : int(5*(rand()/(RAND_MAX+1.0)));
981    
982            shuffle(count);
983        }
984    }
985    
986    void
987  PuzzleStone::on_impulse(const Impulse& impulse)  PuzzleStone::on_impulse(const Impulse& impulse)
988  {  {
989      Cluster c;      if (!oxyd1_compatible()) {
990      bool    is_complete = find_cluster(c);          Cluster c;
991      maybe_move_cluster(c, is_complete, impulse.dir);          bool    is_complete = find_cluster(c);
992            maybe_move_cluster(c, is_complete, impulse.dir);
993        }
994  }  }
995    
996    
# Line 936  PuzzleStone::actor_hit(const StoneContac Line 1001  PuzzleStone::actor_hit(const StoneContac
1001      if (get_connections() == NODIRBIT)      if (get_connections() == NODIRBIT)
1002          return;          return;
1003    
1004      Direction move_dir=get_push_direction(sc);      bool compatible = oxyd1_compatible();
1005    
1006      if (wielded_item_is(sc.actor, "it-magicwand")) {      if (compatible) {
1007          if (cluster_complete()) {          Cluster c;
1008              // make all cluster stones explode          if (find_cluster(c)) {
1009                // make complete cluster explode:
1010                Cluster::iterator e = c.end();
1011                for (Cluster::iterator i = c.begin(); i != e; ++i) {
1012                    KillStone(*i);
1013                    SetItem(*i, MakeItem("it-explosion1"));
1014                }
1015                play_sound("explosion1");
1016              return;              return;
1017          }          }
1018          else if (contact_face(sc) != NODIR) { // not touching a corner      }
1019              Cluster c;  
1020        if (compatible || wielded_item_is(sc.actor, "it-magicwand")) {
1021            Direction face = contact_face(sc);
1022            if (face != NODIR) {    // not touching a corner
1023                Direction move_dir = reverse(face);
1024                Cluster   c;
1025              find_row_or_column_cluster(c, get_pos(), move_dir);              find_row_or_column_cluster(c, get_pos(), move_dir);
1026    
1027              if (move_dir == NODIR) // not enough impulse to move the cluster              if (c.size() == 1) {
1028                    if (!compatible) {
1029                        // if cluster contains single stone -> move it if
1030                        // dest pos is free
1031                        GridPos dest = move(c[0], move_dir);
1032                        if (GetStone(dest) == 0) {
1033                            // check speed. here a lower speed than in
1034                            // get_push_direction() is enough.
1035                            ActorInfo *ai = sc.actor->get_actorinfo();
1036                            if (ai->vel * sc.normal < -2) {
1037    
1038                                Stone *puzz = YieldStone(c[0]);
1039                                SetStone(dest, puzz);
1040                            }
1041                        }
1042                    }
1043                }
1044                else { // otherwise rotate cluster
1045                  rotate_cluster(c);                  rotate_cluster(c);
1046              else              }
                 ; // TODO: move the incomplete cluster  
1047          }          }
1048      }      }
1049      else if (move_dir != NODIR) {      else {
1050          sc.actor->send_impulse(get_pos(), move_dir);          Direction move_dir = get_push_direction(sc);
1051            if (move_dir != NODIR) { // normal push
1052                sc.actor->send_impulse(get_pos(), move_dir);
1053            }
1054      }      }
1055  }  }
1056    
# Line 2371  void stones::Init_complex() Line 2467  void stones::Init_complex()
2467    
2468      Register (new PullStone);      Register (new PullStone);
2469    
2470      Register(new PuzzleStone);      // PerOxyd/Enigma compatible puzzle stones:
2471      Register("st-puzzle-hollow", new PuzzleStone(1));      Register(new PuzzleStone(0, false));
2472      Register("st-puzzle-n", new PuzzleStone(9));      Register("st-puzzle-hollow", new PuzzleStone(1, false));
2473      Register("st-puzzle-e", new PuzzleStone(5));      Register("st-puzzle-n", new PuzzleStone(9, false));
2474      Register("st-puzzle-s", new PuzzleStone(3));      Register("st-puzzle-e", new PuzzleStone(5, false));
2475      Register("st-puzzle-w", new PuzzleStone(2));      Register("st-puzzle-s", new PuzzleStone(3, false));
2476      Register("st-puzzle-ne", new PuzzleStone(13));      Register("st-puzzle-w", new PuzzleStone(2, false));
2477      Register("st-puzzle-nw", new PuzzleStone(10));      Register("st-puzzle-ne", new PuzzleStone(13, false));
2478      Register("st-puzzle-es", new PuzzleStone(7));      Register("st-puzzle-nw", new PuzzleStone(10, false));
2479      Register("st-puzzle-sw", new PuzzleStone(4));      Register("st-puzzle-es", new PuzzleStone(7, false));
2480      Register("st-puzzle-ns", new PuzzleStone(11));      Register("st-puzzle-sw", new PuzzleStone(4, false));
2481      Register("st-puzzle-ew", new PuzzleStone(6));      Register("st-puzzle-ns", new PuzzleStone(11, false));
2482      Register("st-puzzle-nes", new PuzzleStone(15));      Register("st-puzzle-ew", new PuzzleStone(6, false));
2483      Register("st-puzzle-new", new PuzzleStone(14));      Register("st-puzzle-nes", new PuzzleStone(15, false));
2484      Register("st-puzzle-nsw", new PuzzleStone(12));      Register("st-puzzle-new", new PuzzleStone(14, false));
2485      Register("st-puzzle-esw", new PuzzleStone(8));      Register("st-puzzle-nsw", new PuzzleStone(12, false));
2486      Register("st-puzzle-nesw", new PuzzleStone(16));      Register("st-puzzle-esw", new PuzzleStone(8, false));
2487        Register("st-puzzle-nesw", new PuzzleStone(16, false));
2488    
2489        // Oxyd1 compatible puzzle stones:
2490        Register("st-puzzle2-hollow", new PuzzleStone(1, true));
2491        Register("st-puzzle2-n", new PuzzleStone(9, true));
2492        Register("st-puzzle2-e", new PuzzleStone(5, true));
2493        Register("st-puzzle2-s", new PuzzleStone(3, true));
2494        Register("st-puzzle2-w", new PuzzleStone(2, true));
2495        Register("st-puzzle2-ne", new PuzzleStone(13, true));
2496        Register("st-puzzle2-nw", new PuzzleStone(10, true));
2497        Register("st-puzzle2-es", new PuzzleStone(7, true));
2498        Register("st-puzzle2-sw", new PuzzleStone(4, true));
2499        Register("st-puzzle2-ns", new PuzzleStone(11, true));
2500        Register("st-puzzle2-ew", new PuzzleStone(6, true));
2501        Register("st-puzzle2-nes", new PuzzleStone(15, true));
2502        Register("st-puzzle2-new", new PuzzleStone(14, true));
2503        Register("st-puzzle2-nsw", new PuzzleStone(12, true));
2504        Register("st-puzzle2-esw", new PuzzleStone(8, true));
2505        Register("st-puzzle2-nesw", new PuzzleStone(16, true));
2506    
2507      Register (new RotatorStone (true));      Register (new RotatorStone (true));
2508      Register (new RotatorStone (false));      Register (new RotatorStone (false));

Legend:
Removed from v.1.10  
changed lines
  Added in v.1.11

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