/[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.11 by reallysoft, Mon Jun 16 18:39:33 2003 UTC revision 1.12 by reallysoft, Tue Jun 17 17:18:04 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;
   
 //                     if (st->is_kind("st-pull")) {  
 //                         send_impulse(st->get_pos(), dir);  
 //                     }  
 //                     else {  
475                      SendMessage(st, "trigger", Value(dir));                      SendMessage(st, "trigger", Value(dir));
 //                     }  
476                  }                  }
477                  return true;                  return true;
478              }              }
# Line 630  namespace { Line 624  namespace {
624      };      };
625  };  };
626    
627    // ------------------------
628    //      ConnectiveStone
629    // ------------------------
630    // base class for PuzzleStone and BigBrick
631    
632    namespace {
633        class ConnectiveStone : public Stone {
634        public:
635            ConnectiveStone(const char *kind, int connections)
636                : Stone(kind)
637            {
638                set_attrib("connections", connections);
639            }
640    
641            DirectionBits get_connections();
642    
643        private:
644            void init_model();
645            virtual int get_modelno() const;
646        };
647    }
648    
649    DirectionBits
650    ConnectiveStone::get_connections()
651    {
652        int conn=int_attrib("connections") - 1;
653        if (conn >=0 && conn <16)
654            return DirectionBits(conn);
655        else
656            return NODIRBIT;
657    }
658    
659    void
660    ConnectiveStone::init_model() {
661        string modelname = get_kind();
662        char   x[10];
663    
664        sprintf(x, "%d", get_modelno());
665        modelname += x;
666        set_model(modelname);
667    }
668    
669    int
670    ConnectiveStone::get_modelno() const {
671        return int_attrib("connections");
672    }
673    
674    // -----------------
675    //      BigBrick
676    // -----------------
677    // BigBricks allow to build stones of any size
678    
679    namespace {
680        class BigBrick : public ConnectiveStone {
681            CLONEOBJ(BigBrick);
682        public:
683            BigBrick(int connections)
684                : ConnectiveStone("st-bigbrick", connections)
685            {}
686        };
687    }
688    
689    
690  //----------------------------------------  //----------------------------------------
691  // PuzzleStones  // PuzzleStones
692  //----------------------------------------  //----------------------------------------
# Line 705  member of a cluster or not). Line 762  member of a cluster or not).
762  */  */
763  namespace  namespace
764  {  {
765      class PuzzleStone : public Stone {      class PuzzleStone : public ConnectiveStone, public TimeHandler {
766          INSTANCELISTOBJ(PuzzleStone);          INSTANCELISTOBJ(PuzzleStone);
767      public:      public:
768          PuzzleStone(int connections, bool oxyd1_compatible_)          PuzzleStone(int connections, bool oxyd1_compatible_)
769              : Stone("st-puzzle")              : ConnectiveStone("st-puzzle", connections)
770                , state(IDLE)
771          {          {
             set_attrib("connections", connections);  
772              set_attrib("oxyd", int(oxyd1_compatible_));              set_attrib("oxyd", int(oxyd1_compatible_));
773          }          }
774      private:      private:
775          typedef vector<GridPos> Cluster;          typedef vector<GridPos> Cluster;
776    
         DirectionBits get_connections();  
777          bool oxyd1_compatible() const { return int_attrib("oxyd") != 0; }          bool oxyd1_compatible() const { return int_attrib("oxyd") != 0; }
778    
779          static bool visit_dir(vector<GridPos> &stack,          static bool visit_dir(vector<GridPos> &stack, GridPos curpos,
780                                GridPos curpos, Direction dir);                                Direction dir);
781            static void visit_adjacent(vector<GridPos>& stack, GridPos curpos,
782                                       Direction dir, int wanted_oxyd_attrib);
783    
784          bool find_cluster(Cluster &);          bool find_cluster(Cluster &);
785          void find_row_or_column_cluster(Cluster &c,          void find_adjacents(Cluster &);
786                                          GridPos startpos, Direction dir);          void find_row_or_column_cluster(Cluster &c, GridPos startpos,
787                                            Direction  dir, int wanted_oxyd_attrib);
788    
789          bool cluster_complete();          bool cluster_complete();
790          void maybe_move_cluster(Cluster &c, bool is_complete, Direction dir);          void maybe_move_cluster(Cluster &c, bool is_complete, Direction dir);
791          void rotate_cluster(const Cluster &c);          void rotate_cluster(const Cluster &c);
# Line 739  namespace Line 800  namespace
800    
801          virtual void on_impulse(const Impulse& impulse);          virtual void on_impulse(const Impulse& impulse);
802    
         void init_model();  
803          StoneResponse collision_response(const StoneContact &sc);          StoneResponse collision_response(const StoneContact &sc);
804          void actor_hit(const StoneContact &sc);          void actor_hit(const StoneContact &sc);
805          void actor_inside(Actor *a) {          void actor_inside(Actor *a) {
# Line 747  namespace Line 807  namespace
807                  SendMessage(a, "shatter");                  SendMessage(a, "shatter");
808          }          }
809    
810            int get_modelno() const;
811    
812            void trigger_explosion(double delay);
813            static void trigger_explosion_at(GridPos p, double delay);
814            void explode();
815            void alarm();
816    
817          // Variables          // Variables
818          bool visited;           // flag for DFS          bool visited;           // flag for DFS
819    
820            enum { IDLE, EXPLODING } state;
821      };      };
822  }  }
823    
824  PuzzleStone::InstanceList PuzzleStone::instances;  PuzzleStone::InstanceList PuzzleStone::instances;
825    
 DirectionBits  
 PuzzleStone::get_connections()  
 {  
     int conn=int_attrib("connections") - 1;  
     if (conn >=0 && conn <16)  
         return DirectionBits(conn);  
     else  
         return NODIRBIT;  
 }  
   
826  bool  bool
827  PuzzleStone::visit_dir(vector<GridPos> &stack, GridPos curpos, Direction dir)  PuzzleStone::visit_dir(vector<GridPos> &stack, GridPos curpos, Direction dir)
828  {  {
# Line 828  PuzzleStone::find_cluster(Cluster &clust Line 887  PuzzleStone::find_cluster(Cluster &clust
887  }  }
888    
889  void  void
890  PuzzleStone::find_row_or_column_cluster(Cluster &c, GridPos startpos, Direction dir)  PuzzleStone::visit_adjacent(vector<GridPos>& stack, GridPos curpos, Direction dir, int wanted_oxyd_attrib)
891    {
892        GridPos newpos = move(curpos, dir);
893        if (PuzzleStone *pz = dynamic_cast<PuzzleStone*>(GetStone(newpos))) {
894            if (!pz->visited) {
895                if (wanted_oxyd_attrib == pz->int_attrib("oxyd")) {
896                    pz->visited = true;
897                    stack.push_back(newpos);
898                }
899            }
900        }
901    }
902    
903    /* Use a depth first search to determine the group of all puzzle stones
904       with the same "oxyd" attrib that are adjacent to the current stone
905       (or to any other member of the group).
906    */
907    void
908    PuzzleStone::find_adjacents(Cluster &cluster) {
909        for (unsigned i=0; i<instances.size(); ++i)
910            instances[i]->visited=false;
911    
912        vector<GridPos> pos_stack;
913        pos_stack.push_back(get_pos());
914        this->visited = true;
915    
916        int wanted_oxyd_attrib = int_attrib("oxyd");
917    
918        while (!pos_stack.empty()) {
919            GridPos curpos = pos_stack.back();
920            pos_stack.pop_back();
921    
922            cluster.push_back(curpos);
923            visit_adjacent(pos_stack, curpos, NORTH, wanted_oxyd_attrib);
924            visit_adjacent(pos_stack, curpos, SOUTH, wanted_oxyd_attrib);
925            visit_adjacent(pos_stack, curpos, EAST, wanted_oxyd_attrib);
926            visit_adjacent(pos_stack, curpos, WEST, wanted_oxyd_attrib);
927        }
928    }
929    
930    /* searches from 'startpos' into 'dir' for puzzle-stones.
931       wanted_oxyd_attrib == -1 -> take any puzzle stone
932                          else  -> take only puzzle stones of same type
933    */
934    
935    void
936    PuzzleStone::find_row_or_column_cluster(Cluster &c, GridPos startpos, Direction dir, int wanted_oxyd_attrib)
937  {  {
938      assert(dir != NODIR);      assert(dir != NODIR);
939    
940      GridPos p = startpos;      GridPos p = startpos;
941      while (dynamic_cast<PuzzleStone*>(GetStone(p))) {      while (Stone *puzz = dynamic_cast<PuzzleStone*>(GetStone(p))) {
942            if (wanted_oxyd_attrib != -1 && wanted_oxyd_attrib != puzz->int_attrib("oxyd"))
943                break; // stop when an unrequested puzzle stone type is readed
944          c.push_back(p);          c.push_back(p);
945          p.move(dir);          p.move(dir);
946      }      }
# Line 905  PuzzleStone::cluster_complete() Line 1012  PuzzleStone::cluster_complete()
1012      return find_cluster(c);      return find_cluster(c);
1013  }  }
1014    
 void  
 PuzzleStone::init_model()  
 {  
     string modelname = "st-puzzle";  
     char x[10];  
1015    
1016      // Every combination of ``sockets'' has its own model.  int
1017    PuzzleStone::get_modelno() const {
1018      int modelno = int_attrib("connections");      int modelno = int_attrib("connections");
1019      if (oxyd1_compatible()) modelno += 16;      if (oxyd1_compatible()) modelno += 16;
1020      sprintf(x, "%d", modelno);      return modelno;
     modelname += x;  
     set_model(modelname);  
1021  }  }
1022    
1023  void  void
# Line 948  PuzzleStone::shuffle(int count) Line 1049  PuzzleStone::shuffle(int count)
1049      if (oxyd1_compatible()) {      if (oxyd1_compatible()) {
1050          Direction move_dir = Direction(4*(rand()/(RAND_MAX+1.0)));          Direction move_dir = Direction(4*(rand()/(RAND_MAX+1.0)));
1051          Cluster   c;          Cluster   c;
1052          find_row_or_column_cluster(c, get_pos(), reverse(move_dir));          find_row_or_column_cluster(c, get_pos(), reverse(move_dir), 1);
1053          if (!c.empty()) {          if (!c.empty()) {
1054              GridPos last = c.back();              GridPos last = c.back();
1055              c.clear();              c.clear();
1056              find_row_or_column_cluster(c, last, move_dir);              find_row_or_column_cluster(c, last, move_dir, 1);
1057    
1058              // if cluster too small to rotate -> turn direction by 90 deg              // if cluster too small to rotate -> turn direction by 90 deg
1059              if (c.size() <= 1) {              if (c.size() <= 1) {
1060                  move_dir = rotate(move_dir, true);                  move_dir = rotate(move_dir, true);
1061                  c.clear();                  c.clear();
1062                  find_row_or_column_cluster(c, last, move_dir);                  find_row_or_column_cluster(c, last, move_dir, 1);
1063              }              }
1064    
1065              if (c.size() > 1) {              if (c.size() > 1) {
# Line 973  PuzzleStone::shuffle(int count) Line 1074  PuzzleStone::shuffle(int count)
1074      }      }
1075  }  }
1076    
1077  void PuzzleStone::message(const string& msg, const Value &) {  void
1078    PuzzleStone::trigger_explosion(double delay) {
1079        if (state == IDLE) {
1080            state = EXPLODING;
1081            g_timer.set_alarm(this, delay, false);
1082        }
1083    }
1084    
1085    void
1086    PuzzleStone::trigger_explosion_at(GridPos p, double delay) {
1087        PuzzleStone *puzz = dynamic_cast<PuzzleStone*>(GetStone(p));
1088        if (puzz)
1089            puzz->trigger_explosion(delay);
1090    }
1091    
1092    void
1093    PuzzleStone::explode() {
1094        GridPos       p     = get_pos();
1095        DirectionBits dir   = get_connections();
1096        const char    *expl = (dir == NODIRBIT || dir == ALL_DIRECTIONS)
1097            ? "it-explosion2" : "it-explosion1";
1098    
1099        // exchange puzzle stone with explosion
1100        KillStone(p);
1101        SetItem(p, MakeItem(expl));
1102    
1103        // trigger connected neighbors:
1104        if (dir == NODIRBIT) dir = ALL_DIRECTIONS;
1105    
1106        const double DEFAULT_DELAY = 0.2;
1107        if (dir&NORTHBIT) trigger_explosion_at(move(p, NORTH), DEFAULT_DELAY);
1108        if (dir&SOUTHBIT) trigger_explosion_at(move(p, SOUTH), DEFAULT_DELAY);
1109        if (dir&EASTBIT)  trigger_explosion_at(move(p, EAST),  DEFAULT_DELAY);
1110        if (dir&WESTBIT)  trigger_explosion_at(move(p, WEST),  DEFAULT_DELAY);
1111    }
1112    
1113    void
1114    PuzzleStone::alarm() {
1115        explode();
1116    }
1117    
1118    void
1119    PuzzleStone::message(const string& msg, const Value &) {
1120      if (msg == "init") {        // shuffle at level startup      if (msg == "init") {        // shuffle at level startup
1121          int count = options::Difficulty == DIFFICULTY_EASY          int count = options::Difficulty == DIFFICULTY_EASY
1122              ? 1              ? 1
# Line 986  void PuzzleStone::message(const string& Line 1129  void PuzzleStone::message(const string&
1129  void  void
1130  PuzzleStone::on_impulse(const Impulse& impulse)  PuzzleStone::on_impulse(const Impulse& impulse)
1131  {  {
1132      if (!oxyd1_compatible()) {      if (!oxyd1_compatible() && state == IDLE) {
1133          Cluster c;          Cluster c;
1134          bool    is_complete = find_cluster(c);          bool    is_complete = find_cluster(c);
1135          maybe_move_cluster(c, is_complete, impulse.dir);          maybe_move_cluster(c, is_complete, impulse.dir);
1136      }      }
1137  }  }
1138    
   
   
1139  void  void
1140  PuzzleStone::actor_hit(const StoneContact &sc)  PuzzleStone::actor_hit(const StoneContact &sc)
1141  {  {
1142      if (get_connections() == NODIRBIT)      if (get_connections() == NODIRBIT)
1143          return;          return;
1144    
1145        if (state == EXPLODING)
1146            return;
1147    
1148      bool compatible = oxyd1_compatible();      bool compatible = oxyd1_compatible();
1149    
1150      if (compatible) {      if (compatible) {
1151          Cluster c;          Cluster c;
1152          if (find_cluster(c)) {          if (find_cluster(c)) {
1153              // make complete cluster explode:              Cluster all;
1154              Cluster::iterator e = c.end();              find_adjacents(all);
1155              for (Cluster::iterator i = c.begin(); i != e; ++i) {  
1156                  KillStone(*i);              if (all.size() == c.size()) {
1157                  SetItem(*i, MakeItem("it-explosion1"));                  explode();          // explode complete cluster
1158                    return;
1159              }              }
             play_sound("explosion1");  
             return;  
1160          }          }
1161      }      }
1162    
# Line 1022  PuzzleStone::actor_hit(const StoneContac Line 1165  PuzzleStone::actor_hit(const StoneContac
1165          if (face != NODIR) {    // not touching a corner          if (face != NODIR) {    // not touching a corner
1166              Direction move_dir = reverse(face);              Direction move_dir = reverse(face);
1167              Cluster   c;              Cluster   c;
1168              find_row_or_column_cluster(c, get_pos(), move_dir);              find_row_or_column_cluster(c, get_pos(), move_dir, int(compatible));
1169    
1170              if (c.size() == 1) {              if (c.size() == 1) {
1171                  if (!compatible) {                  if (!compatible) {
1172                      // if cluster contains single stone -> move it if                      // if cluster contains single stone
1173                      // dest pos is free                      // -> move it if dest pos is free
1174                      GridPos dest = move(c[0], move_dir);                      GridPos dest = move(c[0], move_dir);
1175                      if (GetStone(dest) == 0) {                      if (GetStone(dest) == 0) {
1176                          // check speed. here a lower speed than in                          // check speed. here a lower speed than in
# Line 2504  void stones::Init_complex() Line 2647  void stones::Init_complex()
2647      Register("st-puzzle2-esw", new PuzzleStone(8, true));      Register("st-puzzle2-esw", new PuzzleStone(8, true));
2648      Register("st-puzzle2-nesw", new PuzzleStone(16, true));      Register("st-puzzle2-nesw", new PuzzleStone(16, true));
2649    
2650        Register("st-bigbrick", new BigBrick(1));
2651        Register("st-bigbrick-n", new BigBrick(9));
2652        Register("st-bigbrick-e", new BigBrick(5));
2653        Register("st-bigbrick-s", new BigBrick(3));
2654        Register("st-bigbrick-w", new BigBrick(2));
2655        Register("st-bigbrick-ne", new BigBrick(13));
2656        Register("st-bigbrick-nw", new BigBrick(10));
2657        Register("st-bigbrick-es", new BigBrick(7));
2658        Register("st-bigbrick-sw", new BigBrick(4));
2659        Register("st-bigbrick-ns", new BigBrick(11));
2660        Register("st-bigbrick-ew", new BigBrick(6));
2661        Register("st-bigbrick-nes", new BigBrick(15));
2662        Register("st-bigbrick-new", new BigBrick(14));
2663        Register("st-bigbrick-nsw", new BigBrick(12));
2664        Register("st-bigbrick-esw", new BigBrick(8));
2665        Register("st-bigbrick-nesw", new BigBrick(16));
2666    
2667      Register (new RotatorStone (true));      Register (new RotatorStone (true));
2668      Register (new RotatorStone (false));      Register (new RotatorStone (false));
2669    

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

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