001    package jagafa.ai;
002    
003    import jagafa.JassRound;
004    import jagafa.flags.AIFlags;
005    import jagafa.flags.TestingFlags;
006    import jagafa.object.CardList;
007    import jagafa.object.Hand;
008    import jagafa.object.Player;
009    import jagafa.rule.ObenRules;
010    import jagafa.rule.RuleSet;
011    import jagafa.rule.UntenRules;
012    import jagafa.scores.ScoreTable;
013    import jagafa.stats.CardTool;
014    import jagafa.stats.PlayerStats;
015    
016    import java.util.List;
017    
018    public abstract class RuleSetChoiceAI {
019    
020            private static final int COLORS = 4;
021    
022            private static Player player_;
023    
024            private static ScoreTable scoreTable_;
025    
026            private static JassRound round_;
027    
028            public static RuleSet chooseRuleSet(Player p, JassRound round) {
029    
030                    player_ = p;
031                    scoreTable_ = round.getScoreTable();
032                    round_ = round;
033    
034                    List<RuleSet> rules_ = scoreTable_.getRules();
035    
036                    RuleSet rule = null;
037    
038                    double estimates[] = new double[rules_.size()];
039                    Hand h = player_.getHand();
040                    if (TestingFlags.ruleSetChoiceDump_) {
041                            //System.out.println("Player's hand: " + h);
042                    }
043                    int highest = -10;
044                    double highestEstimate = -100;
045                    double gradeWeight = AIFlags.GRADE_WEIGHT;
046    
047                    for (int i = 0; i < rules_.size(); i++) {
048    
049                            estimates[i] = gradeWeight * gradeRuleSet(rules_.get(i));
050                            if (rules_.get(i).getName().startsWith("Slalom")) {
051                                    estimates[i] = gradeSlalom(rules_.get(i));
052                            }
053    
054                            //estimates[i] += (1 - gradeWeight) * estimateScore(rules_.get(i));
055                            if (estimates[i] > highestEstimate) {
056                                    highest = i;
057                                    highestEstimate = estimates[i];
058                            }
059                    }
060    
061                    if (TestingFlags.ruleSetChoiceDump_) {
062                            System.out.println("\nStrength estimates: ");
063                            for (int i = 0; i < rules_.size(); i++) {
064                                    System.out.println(rules_.get(i).getName() + "     \t" + estimates[i]);
065    
066                            }
067                    }
068                    if (highestEstimate < AIFlags.CHANGE_TRESHOLD) {
069    
070                            if (scoreTable_.canChangeChoosingPlayer()) {
071                                    return null;
072                            }
073                    }
074    
075                    rule = rules_.get(highest);
076    
077                    return rule;
078    
079            }
080    
081            private static double gradeSlalom(RuleSet set) {
082                    ObenRules oben = new ObenRules();
083                    UntenRules unten = new UntenRules();
084    
085                    double obenEst = gradeRuleSet(oben);
086                    double untenEst = gradeRuleSet(unten);
087    
088                    JassRound round = new JassRound(oben);
089    
090                    int secureOben = 0;
091                    int addOben = 0;
092                    PlayerStats stats_ = new PlayerStats(round, player_);
093                    CardList bockList[] = stats_.getBockList();
094    
095                    for (int i = 0; i < COLORS; i++) {
096                            secureOben += bocksOfColorInRow(bockList, i);
097                            CardList colorList = stats_.getColorList()[i];
098    
099                            int addOfColor = (colorList.size() - secureOben);
100                            if (addOfColor > 2) {
101                                    addOben += addOfColor;
102                            }
103    
104                    }
105    
106                    round = new JassRound(oben);
107    
108                    int secureUnten = 0;
109                    int addUnten = 0;
110                    stats_ = new PlayerStats(round, player_);
111                    bockList = stats_.getBockList();
112    
113                    for (int i = 0; i < COLORS; i++) {
114                            secureUnten += bocksOfColorInRow(bockList, i);
115    
116                            CardList colorList = stats_.getColorList()[i];
117    
118                            int addOfColor = (colorList.size() - secureUnten);
119                            if (addOfColor > 2) {
120                                    addUnten += addOfColor;
121                            }
122    
123                    }
124    
125                    int diff = Math.abs(secureOben - secureUnten);
126                    double xxx = 1/(diff+0.5);
127                    
128                    return xxx*(secureOben+secureUnten);
129            }
130    
131            public static double gradeRuleSet(RuleSet rule) {
132                    double scoreEstimate = 0;
133    
134                    Hand h = player_.getHand();
135    
136                    round_.setRules(rule);
137                    PlayerStats stats_ = new PlayerStats(round_, player_);
138    
139                    CardList bockList[] = stats_.getBockList();
140                    for (int i = 0; i < bockList.length; i++) {
141                            CardList nthBock = bockList[i];
142                            int nrOfNth = nthBock.size();
143    
144                            scoreEstimate += (double) ((1 / ((double) i + 1)) * (double) nrOfNth);
145                            //System.out.print(nrOfNth + ";"+ scoreEstimate + " " );
146                    }
147    
148                    int numberOfColors = 0;
149    
150                    for (int i = 0; i < COLORS; i++) {
151                            CardList ofCol = CardTool.getAllOfColor(h, i);
152    
153                            int nrOfCol = ofCol.size();
154                            if (nrOfCol > 0) {
155                                    numberOfColors++;
156                            }
157                            scoreEstimate += (double) (nrOfCol - 2 > 0 ? nrOfCol - 2 : 1)
158                                            * (double) bocksOfColorInRow(bockList, i);
159                    }
160                    scoreEstimate += numberOfColors;
161                    return (double) (Math.round(scoreEstimate * 1000.0) / 1000.0);
162    
163            }
164    
165            private static int bocksOfColorInRow(CardList bockList[], int color) {
166                    int inarow = 0;
167                    boolean fail = false;
168                    for (int i = 0; i < bockList.length; i++) {
169                            CardList nthBock = bockList[i];
170                            CardList bockColor = CardTool.getAllOfColor(nthBock, color);
171    
172                            if (bockColor.size() == 0) {
173                                    /*if (fail) {
174                                     return inarow;
175                                     }
176                                     fail = true;
177                                     inarow++;*/
178                                    return inarow;
179                            } else {
180                                    inarow++;
181                            }
182    
183                    }
184    
185                    return inarow;
186            }
187    
188            public static int estimateScore(RuleSet rule) {
189                    int strikesEstimate = 0;
190    
191                    Hand h = player_.getHand();
192    
193                    round_.setRules(rule);
194                    PlayerStats stats_ = new PlayerStats(round_, player_);
195    
196                    CardList bockList[] = stats_.getBockList();
197    
198                    for (int i = 0; i < bockList.length; i++) {
199                            CardList nthBock = bockList[i];
200                            int nrOfNth = nthBock.size();
201    
202                    }
203                    int directStrikes = 0;
204                    int additionalEstimate = 0;
205                    for (int i = 0; i < COLORS; i++) {
206                            int secureStrikes = bocksOfColorInRow(bockList, i);
207                            directStrikes += secureStrikes;
208                            CardList colorList = stats_.getColorList()[i];
209    
210                            int addOfColor = (colorList.size() - secureStrikes);
211                            if (addOfColor > 2) {
212                                    additionalEstimate += addOfColor;
213                            }
214    
215                    }
216    
217                    double directWeight = 22.0;
218                    double addWeight = 10.0;
219                    double mult = addWeight / directWeight;
220    
221                    strikesEstimate = directStrikes + (int) Math.round(mult * additionalEstimate);
222    
223                    double scoreEst = directStrikes * directWeight + additionalEstimate * addWeight;
224    
225                    /*
226                     System.out.print("For " + rule.getName().toUpperCase() + "\t");
227                     System.out.println("Estimated Score: " + scoreEst);
228                     System.out.println("Where:\tdirect: " + directStrikes + "\tadditional: " + additionalEstimate);
229                     System.out.println("Weighted:\t" + strikesEstimate + "\n");
230                     */
231    
232                    return strikesEstimate;
233            }
234    }