1 /*
2     Bastet - tetris clone with embedded bastard block chooser
3     (c) 2005-2009 Federico Poloni <f.polonithirtyseven@sns.it> minus 37
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef BASTET_BLOCK_CHOOSER_HPP
20 #define BASTET_BLOCK_CHOOSER_HPP
21 
22 #include "BlockChooser.hpp"
23 
24 #include "Well.hpp"
25 
26 #include <boost/unordered_set.hpp>
27 #include <set>
28 #include <boost/functional/hash.hpp>
29 
30 namespace Bastet{
31 
32   static const long GameOverScore=-1000; //bogus score assigned to combinations which cause game over
33 
34 //  declared in Well.hpp
35   long Evaluate(const Well *w, int extralines=0); //assigns a score to a position w + a number of extra lines deleted while getting there
36 
37   typedef BlockPosition Vertex;
38 
39   //generic visitor that "does something" with a possible drop position
40   class WellVisitor{
41   public:
WellVisitor()42     WellVisitor(){}
Visit(BlockType b,const Well * well,Vertex v)43     virtual void Visit(BlockType b, const Well *well, Vertex v){};
~WellVisitor()44     virtual ~WellVisitor(){};
45   };
46 
47   //for each block type, drops it (via a BestScoreVisitor) and sees which block reaches the best score along the drop positions
48   class RecursiveVisitor: public WellVisitor{
49   public:
50     RecursiveVisitor();
51     virtual ~RecursiveVisitor();
52     virtual void Visit(BlockType b, const Well *well, Vertex v);
GetScores() const53     const boost::array<long,7> &GetScores() const{return _scores;}
54   private:
55     typedef boost::array<long,7> ScoresList;
56     ScoresList _scores;
57   };
58 
59   //returns the max score over all drop positions
60   class BestScoreVisitor: public WellVisitor{
61   public:
62     explicit BestScoreVisitor(int bonusLines=0);
63     virtual ~BestScoreVisitor();
64     virtual void Visit(BlockType b, const Well *well, Vertex v);
GetScore() const65     long GetScore() const{return _score;}
66   private:
67     long _score;
68     int _bonusLines;
69   };
70 
71   /**
72    * Tries to drop a block in all possible positions, and invokes the visitor on each one
73    */
74   class Searcher{
75   public:
76     Searcher(BlockType b, const Well *well, Vertex v, WellVisitor *visitor);
77   private:
78     boost::unordered_set<Vertex> _visited;
79     //std::set<Vertex> _visited; ^^ the above is more efficient, we need to do many inserts
80     BlockType _block;
81     const Well *_well;
82     WellVisitor *_visitor;
83     void DFSVisit(Vertex v);
84   };
85 
86   class BastetBlockChooser: public BlockChooser{
87   public:
88     BastetBlockChooser();
89     virtual ~BastetBlockChooser();
90     virtual Queue GetStartingQueue();
91     virtual BlockType GetNext(const Well *well, const Queue &q);
92     /**
93      * computes "scores" of the candidate next blocks by dropping them in all possible positions and choosing the one that has the least max_(drop positions) Evaluate(well)
94      */
95     boost::array<long,7> ComputeMainScores(const Well *well, BlockType currentBlock);
96 
97   private:
98 
99   };
100 
101   //block chooser similar to the older bastet versions, does not give a block preview
102   class NoPreviewBlockChooser:public BlockChooser{
103   public:
104     NoPreviewBlockChooser();
105     virtual ~NoPreviewBlockChooser();
106     virtual Queue GetStartingQueue();
107     virtual BlockType GetNext(const Well *well, const Queue &q);
108   };
109 
110 }
111 
112 #endif //BASTET_BLOCK_CHOOSER_HPP
113