From 0df45ffc94fb426654502cbcd8e753e134553469 Mon Sep 17 00:00:00 2001 From: Tom-from-6520 Date: Thu, 16 Jul 2020 16:09:31 -0400 Subject: [PATCH 1/3] hehe true random game everytime --- ginrummy/GinRummyMavenProject/.classpath | 27 +++++++++++++++++++ ginrummy/GinRummyMavenProject/.gitignore | 1 + ginrummy/GinRummyMavenProject/.project | 23 ++++++++++++++++ .../.settings/org.eclipse.jdt.core.prefs | 13 +++++++++ .../main/java/TurnStatesDataCollector.java | 11 ++++---- 5 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 ginrummy/GinRummyMavenProject/.classpath create mode 100644 ginrummy/GinRummyMavenProject/.gitignore create mode 100644 ginrummy/GinRummyMavenProject/.project create mode 100644 ginrummy/GinRummyMavenProject/.settings/org.eclipse.jdt.core.prefs diff --git a/ginrummy/GinRummyMavenProject/.classpath b/ginrummy/GinRummyMavenProject/.classpath new file mode 100644 index 0000000..5e8a55f --- /dev/null +++ b/ginrummy/GinRummyMavenProject/.classpath @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ginrummy/GinRummyMavenProject/.gitignore b/ginrummy/GinRummyMavenProject/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/ginrummy/GinRummyMavenProject/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/ginrummy/GinRummyMavenProject/.project b/ginrummy/GinRummyMavenProject/.project new file mode 100644 index 0000000..850c579 --- /dev/null +++ b/ginrummy/GinRummyMavenProject/.project @@ -0,0 +1,23 @@ + + + GinRummyMavenProject + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/ginrummy/GinRummyMavenProject/.settings/org.eclipse.jdt.core.prefs b/ginrummy/GinRummyMavenProject/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..8445b6b --- /dev/null +++ b/ginrummy/GinRummyMavenProject/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,13 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/ginrummy/GinRummyMavenProject/src/main/java/TurnStatesDataCollector.java b/ginrummy/GinRummyMavenProject/src/main/java/TurnStatesDataCollector.java index 1299bbd..d95898f 100644 --- a/ginrummy/GinRummyMavenProject/src/main/java/TurnStatesDataCollector.java +++ b/ginrummy/GinRummyMavenProject/src/main/java/TurnStatesDataCollector.java @@ -25,7 +25,7 @@ public class TurnStatesDataCollector { /** * Random number generator */ - private static final Random RANDOM = new Random(); + private static Random random; /** * Hand size (before and after turn). After draw and before discard there is one extra card. @@ -57,7 +57,8 @@ public class TurnStatesDataCollector { * Play a game of Gin Rummy and return the winning player number 0 or 1. Add a new TurnState in line 132 * @return the winning player number 0 or 1 */ - public int play(int startingPlayer, GinRummyPlayer player0, GinRummyPlayer player1) { + public int play(int startingPlayer, GinRummyPlayer player0, GinRummyPlayer player1, long randSeed) { + random = new Random(randSeed); players = new GinRummyPlayer[] {player0, player1}; int[] scores = new int[2]; ArrayList> hands = new ArrayList<>(); @@ -67,7 +68,7 @@ public int play(int startingPlayer, GinRummyPlayer player0, GinRummyPlayer playe //game states with 2 vectors of turnStates to store one's own actions and hands ArrayList>> gameData = new ArrayList<>(); - + while (scores[0] < GinRummyUtil.GOAL_SCORE && scores[1] < GinRummyUtil.GOAL_SCORE) { // while game not over //create a variable to store turns' states @@ -82,7 +83,7 @@ public int play(int startingPlayer, GinRummyPlayer player0, GinRummyPlayer playe int opponent = (currentPlayer == 0) ? 1 : 0; // get shuffled deck and deal cards - Stack deck = Card.getShuffle(RANDOM.nextInt()); + Stack deck = Card.getShuffle(random.nextInt()); hands.get(0).clear(); hands.get(1).clear(); for (int i = 0; i < 2 * HAND_SIZE; i++) @@ -427,7 +428,7 @@ public static void main(String[] args) { TurnStatesDataCollector collector = new TurnStatesDataCollector(); int numGameBig = 25000; for(int i = 0; i < numGameBig; i++) - collector.play(i%2, new SimpleGinRummyPlayer(), new SimpleGinRummyPlayer()); + collector.play(i%2, new SimpleGinRummyPlayer(), new SimpleGinRummyPlayer(), (long)i); long startMs = System.currentTimeMillis(); collector.saveGame("play_data_SimplePlayer.dat", playData); From ccfae8804768ecbe13aa026333d940bbaf7b807f Mon Sep 17 00:00:00 2001 From: Tom-from-6520 Date: Fri, 24 Jul 2020 11:31:21 -0400 Subject: [PATCH 2/3] adding HandEstimator3 --- .../src/main/java/HandEstimator3.java | 478 ++++++++++++++++++ .../src/main/java/HandEstimatorGeneral.java | 66 +++ .../src/main/java/Maths.java | 17 + .../src/main/java/Util.java | 16 + 4 files changed, 577 insertions(+) create mode 100644 ginrummy/GinRummyMavenProject/src/main/java/HandEstimator3.java create mode 100644 ginrummy/GinRummyMavenProject/src/main/java/HandEstimatorGeneral.java diff --git a/ginrummy/GinRummyMavenProject/src/main/java/HandEstimator3.java b/ginrummy/GinRummyMavenProject/src/main/java/HandEstimator3.java new file mode 100644 index 0000000..8a45ff9 --- /dev/null +++ b/ginrummy/GinRummyMavenProject/src/main/java/HandEstimator3.java @@ -0,0 +1,478 @@ +import java.util.ArrayList; + +public class HandEstimator3 extends HandEstimatorGeneral{ + + private static final boolean VERBOSE = false; + + private static final float IGNORE_THRESHOLD_RATIO = 0.5f; + + private static final float PREV_TURN_IMPORTANT_POWER = 0.1f; + + // Known card in the opponent hand + boolean[] op_known; + + // other known cards that are not in op hand + boolean[] other_known; + + // prob in the opponent hand + double[] probs; + + // Total unknown + int n_unknown; + + public HandEstimator3() {} + + + public void init() { + op_known = new boolean[52]; + other_known = new boolean[52]; + probs = new double[52]; + + // Initialize number of unknown card + re_calculate_unknown(); + + // Initialize probability + for (int i = 0; i < probs.length; i++) { + probs[i] = (float) (1.0 / n_unknown); + } + + re_mask_prob(); + + } + + + + + /** + * Bayes thinsg/ algorithms + */ + + + + + @SuppressWarnings("unused") + private static double prob_card (double prob_bayes_draw, double prob_bayes_discard) { + return prob_bayes_draw * prob_bayes_discard; + } + + @SuppressWarnings("unused") + private static double[] prob_card (double[] prob_bayes_draw, double[] prob_bayes_discard) { + double[] y_card = new double[52]; + for (int i = 0; i < y_card.length; i++) { + y_card[i] = prob_card(prob_bayes_draw[i], prob_bayes_discard[i]); + } + return y_card; + } + + + + + private static double prob_bayes_discard(double meld_prop, double to_prop) { + return meld_prop * Math.pow(to_prop, PREV_TURN_IMPORTANT_POWER) * 11; + } + + private static double[] prob_bayes_discard(double[] meld_prop, double[] to_prop) { + assert meld_prop.length == to_prop.length; + double[] y = new double[meld_prop.length]; + for (int i = 0; i < meld_prop.length; i++) { + y[i] = prob_bayes_discard(meld_prop[i], to_prop[i]); + } + return y; + } + + private static double prob_bayes_draw(double meld_prop, double to_prop) { + return meld_prop * Math.pow(to_prop, PREV_TURN_IMPORTANT_POWER) * 2; + } + + private static double[] prob_bayes_draw(double[] meld_prop, double[] to_prop) { + assert meld_prop.length == to_prop.length; + double[] y = new double[meld_prop.length]; + for (int i = 0; i < meld_prop.length; i++) { + y[i] = prob_bayes_draw(meld_prop[i], to_prop[i]); + } + return y; + } + + @SuppressWarnings("unused") + private double[] get_meld_draw(Card op_draw, boolean drawn) { + double[] y = new double[52]; + if (drawn) { + for (int i = 0; i < y.length; i++) { + y[i] = (1.0/n_unknown); + } + y[op_draw.getId()] = 1; + // mask 1 around draw card + int rank = op_draw.getRank(); + int suit = op_draw.getSuit(); + for (int r = rank - 2; r <= rank + 2; r++) { + if (r < 0) continue; + if (r > 12) continue; + y[new Card(r, suit).getId()] = 1; + } + + for (int s = suit - 3; s <= suit + 3; s++) { + if (s < 0) continue; + if (s > 3) continue; + y[new Card(rank, s).getId()] = 1; + } + } else { + for (int i = 0; i < y.length; i++) { + y[i] = (1.0/n_unknown); + } + y[op_draw.getId()] = (1.0/n_unknown * IGNORE_THRESHOLD_RATIO); + // mask 1 around draw card + int rank = op_draw.getRank(); + int suit = op_draw.getSuit(); + + for (int r = rank - 2; r <= rank + 2; r++) { + if (r < 0) continue; + if (r > 12) continue; + y[new Card(r, suit).getId()] = (1.0/n_unknown * IGNORE_THRESHOLD_RATIO); + } + + for (int s = suit - 3; s <= suit + 3; s++) { + if (s < 0) continue; + if (s > 3) continue; + y[new Card(rank, s).getId()] = (1.0/n_unknown * IGNORE_THRESHOLD_RATIO); + } + } + return y; + } + + private double[] get_meld_discard(Card op_discard) { + + if (op_discard == null) { + return new double[52]; + } + + double[] y = new double[52]; + + for (int i = 0; i < y.length; i++) { + y[i] = (1.0/n_unknown); + } + + y[op_discard.getId()] = (1.0/n_unknown * IGNORE_THRESHOLD_RATIO); + + // mask 1 around discard card + int rank = op_discard.getRank(); + int suit = op_discard.getSuit(); + + for (int r = rank - 2; r <= rank + 2; r++) { + if (r < 0) continue; + if (r > 12) continue; + y[new Card(r, suit).getId()] = (1.0/n_unknown * IGNORE_THRESHOLD_RATIO); + } + + for (int s = suit - 3; s <= suit + 3; s++) { + if (s < 0) continue; + if (s > 3) continue; + y[new Card(rank, s).getId()] = (1.0/n_unknown * IGNORE_THRESHOLD_RATIO); + } + + return y; + } + + + /** + * https://en.wikipedia.org/wiki/Feature_scaling + * @param mat + * @return + */ + @SuppressWarnings("unused") + private static double[] normalize(double[] mat, String method) { + // 84.35 % and vary ( 60 - 80) + if (method.equals("maxmin")) { + double[] y = new double[mat.length]; + + double min = Float.MAX_VALUE; + double max = Float.MIN_VALUE; + + // Get max min + for(int i = 0; i < mat.length; i++) { + if (mat[i] > max) { + max = mat[i]; + } + if (mat[i] < min) { + min = mat[i]; + } + } + + double distance = max - min; + + for(int i = 0; i < mat.length; i++) { + y[i] = (mat[i] - min) / distance; + } + + return y; + } + + // 82.67 % acc + else if (method.equals("probone")) { + double normalizing_sum = 0; + double[] y = new double[mat.length]; + + for (int i = 0; i < y.length; i++) { + double prob = mat[i]; + if (prob < 0) { + prob = 0; + } + normalizing_sum += prob; + } + + + for (int i = 0; i < y.length; i++) { + if (normalizing_sum != 0) { + y[i] = (Math.max(0.0, mat[i]) / normalizing_sum); + } else { + y[i] = (1.0 / 42); + } + } + + return y; + } + // 60 % acc due to out side 1 + else if (method.equals("standard_scale")) { + double mean = Maths.mean(mat); + double std = Maths.std(mat); + + double[] y = new double[mat.length]; + for(int i = 0; i < y.length; i++) { + y[i] = (mat[i] - mean) / std; + } + return y; + } else { + return mat; + } + } + + /** + * Default normalize method min-max scaling + * https://en.wikipedia.org/wiki/Feature_scaling + * @param probs2 + * @return + */ + @SuppressWarnings("unused") + private static double[] normalize(double[] probs2) { + double normalizing_sum = 0; + double[] y = new double[probs2.length]; + + for (int i = 0; i < y.length; i++) { + double prob = probs2[i]; + if (prob < 0) { + prob = 0; + } + normalizing_sum += prob; + } + + + for (int i = 0; i < y.length; i++) { + if (normalizing_sum != 0) { + y[i] = (Math.max(0.0, probs2[i]) / normalizing_sum); + } else { + y[i] = (1.0 / 42); + } + } + + return y; + } + + /** + * Default normalize method + * https://en.wikipedia.org/wiki/Feature_scaling + * @param mat + * @return + */ + @SuppressWarnings("unused") + private static double[] normalize(double[] mat, int turn) { + if (turn == 0) { + return mat; + } + float threshold = 1 - (1.0f / turn); +// System.out.println("Turn : " + turn + " ; Threshold: " + threshold); + double[] y = new double[52]; + double max = Float.MIN_VALUE; + // Get max min + for(int i = 0; i < mat.length; i++) { + if (mat[i] > max) { + max = mat[i]; + } + } +// System.out.println(" ; ratio: " + threshold / max); + for(int i = 0; i < mat.length; i++) { + y[i] = mat[i] * (threshold / max); +// System.out.println("Before: " + mat[i]); +// System.out.println("After: " + mat[i] * (threshold / max)); + } + + return y; + } + + + /** + * Return the probability of opponent meld + * @return + */ + public int get_op_nmeld() { + // Hard code + int count = 1; + for (boolean b : this.op_known) { + if (b) count++; + } + return count; + } + + + public void setOpKnown(Card card, boolean b) { +// if (VERBOSE) if (b) System.out.println("The opponent has the card " + card.toString()); + op_known[card.getId()] = b; + } + + public void setOpKnown(ArrayList hand, boolean b) { + for (Card c : hand) { + setOpKnown(c, b); + } + } + + public void setOtherKnown(Card card, boolean b) { +// if (VERBOSE) if (b) System.out.println("The opponent has the card " + card.toString()); + other_known[card.getId()] = b; + } + + public void setOtherKnown(ArrayList hand, boolean b) { + for (Card c : hand) { + setOtherKnown(c, b); + } + } + + @Override + public void reportDrawDiscard(Card faceUpCard, boolean drawn, Card discardedCard) { +// if (VERBOSE) System.out.println("The opponent " + (b ? "" : "does not ") +"draw card " + faceUpCard.toString() + " and discard " + (discardedCard == null ? "null" : discardedCard.toString())); + // Set known everything + setOpKnown(faceUpCard, drawn); + setOtherKnown(faceUpCard, !drawn); + setOtherKnown(discardedCard, discardedCard != null); + + // Remask + re_mask_prob(); + // Recalculate n_unknown card + re_calculate_unknown(); + // normalize + this.probs = normalize(this.probs); + + // Get masking melding + double[] meld_draw = get_meld_draw(faceUpCard, drawn); + double[] meld_discard = get_meld_discard(discardedCard); + +// if (VERBOSE ) { +// print_mat(meld_draw, "Masking drawing meld"); +// print_mat(meld_discard, "Masking discarding meld"); +// } + + double[] bayes_draw = prob_bayes_draw(meld_draw, this.probs); + double[] bayes_discard = prob_bayes_discard(meld_discard, this.probs); + +// if (VERBOSE ) { +// print_mat(bayes_draw, "Bayes drawing meld"); +// print_mat(bayes_discard, "Bayes discarding meld"); +// } + + this.probs = prob_card(bayes_draw, bayes_discard); + re_mask_prob(); + this.probs = normalize(this.probs); + + } + + + + private void re_mask_prob() { + for (int i = 0; i < this.probs.length; i++) { + if (this.op_known[i]) { + this.probs[i] = 1; + } + if (this.other_known[i]) { + this.probs[i] = 0; + } + } + } + + + private void re_calculate_unknown() { + this.n_unknown = 0; + for (int i = 0; i < this.probs.length; i++) { + if (!this.op_known[i] && !this.other_known[i]) { + this.n_unknown++; + } + } +// System.out.println("Number of unknown cards: " + n_unknown); + } + + /** + * Get set + * @return + */ + + @Override + public double[] getProb() { + return this.probs; + } + + @Override + public boolean[] getKnown() { + return this.op_known; + } + + @Override + public void setKnown(ArrayList cards, boolean held) { + if(held) + for(Card c : cards) + op_known[c.getId()] = true; + else + for(Card c : cards) + other_known[c.getId()] = true; + + // Recalculate n_unknown card + re_calculate_unknown(); + // Remask + re_mask_prob(); + // normalize + this.probs = normalize(this.probs); + } + + + public static float cal_accuracy(ArrayList op_hand, float[] pred) { + + float[] op_mat = new float[pred.length]; + + for (Card c : op_hand) { + op_mat[c.getId()] = 1; + } + + float sum = 0; + for (int i = 0; i < op_mat.length; i++) { + sum += 1 - Math.abs(op_mat[i] - pred[i]); + } + + return sum / 52; + } + + public static float cal_accuracy(float[] op_mat, float[] pred) { + + float sum = 0; + for (int i = 0; i < op_mat.length; i++) { + sum += 1 - Math.abs(op_mat[i] - pred[i]); + } + + return sum / 52; + } + + + public void view() { + Util.print_mat(this.op_known, "Cards that are exactly in opponent's hand"); + Util.print_mat(this.other_known, "Cards that are in my hand or discard pile"); + Util.print_mat(this.probs, "Probability of opponent's hand"); + } + + public static void main(String[] args) { + // TODO Auto-generated method stub + } +} diff --git a/ginrummy/GinRummyMavenProject/src/main/java/HandEstimatorGeneral.java b/ginrummy/GinRummyMavenProject/src/main/java/HandEstimatorGeneral.java new file mode 100644 index 0000000..32ca660 --- /dev/null +++ b/ginrummy/GinRummyMavenProject/src/main/java/HandEstimatorGeneral.java @@ -0,0 +1,66 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; + +public abstract class HandEstimatorGeneral{ + + public abstract double[] getProb(); + + public abstract boolean[] getKnown(); + +// public abstract void setKnown(Card card, boolean held); + + public abstract void setKnown(ArrayList cards, boolean held); + + public abstract void reportDrawDiscard(Card faceUpCard, boolean drawn, Card discardedCard); + + + public ArrayList getEstimatedHand() { + + ArrayList hand = new ArrayList(); + ArrayList> temp = new ArrayList>(); + double[] prob = getProb(); + boolean[] known = getKnown(); + + for (int id = 0; id < 52; id++) + if (known[id]) + hand.add(Card.strCardMap.get(Card.idStrMap.get(id))); + else + temp.add(new ArrayList(Arrays.asList(prob[id], (double) id))); + + int theRest = 10 - hand.size(); // the left number of unknown cards + Collections.sort(temp, new Comparator>() + { + @Override + public int compare(ArrayList a, ArrayList b) { + if (a.get(0) < b.get(0)) + return 1; + else if (a.get(0) > b.get(0)) + return -1; + return 0; + } + }); + + ArrayList uniqueID = new ArrayList(); + for (int i = 0; i < temp.size(); i++) + { + if (i > 0 && temp.get(i).get(0) != temp.get(i-1).get(0)) + { + uniqueID.add((int)Math.floor(temp.get(i-1).get(1))); + theRest--; + if (theRest == 0) + { + for (int id: uniqueID) + hand.add(Card.strCardMap.get(Card.idStrMap.get(id))); + break; + } + } + } +// estimatedHand = hand; + return hand; + } + + + +} diff --git a/ginrummy/GinRummyMavenProject/src/main/java/Maths.java b/ginrummy/GinRummyMavenProject/src/main/java/Maths.java index 8011714..cb620b0 100644 --- a/ginrummy/GinRummyMavenProject/src/main/java/Maths.java +++ b/ginrummy/GinRummyMavenProject/src/main/java/Maths.java @@ -9,6 +9,14 @@ public static float mean (float[] x) { return sum / x.length; } + public static double mean (double[] x) { + double sum = 0; + for (double f : x) { + sum += f; + } + return sum / x.length; + } + public static float std (float[] x) { float sum = 0; float mean = mean(x); @@ -18,6 +26,15 @@ public static float std (float[] x) { return (float) Math.sqrt(sum / x.length); } + public static double std (double[] x) { + double sum = 0; + double mean = mean(x); + for (double f : x) { + sum += Math.pow((f - mean), 2); + } + return Math.sqrt(sum / x.length); + } + public static void main(String[] args) { float[] a = {2, 4, 6}; System.out.println("Mean: " + mean(a)); diff --git a/ginrummy/GinRummyMavenProject/src/main/java/Util.java b/ginrummy/GinRummyMavenProject/src/main/java/Util.java index 10e2d6f..b4ef06a 100644 --- a/ginrummy/GinRummyMavenProject/src/main/java/Util.java +++ b/ginrummy/GinRummyMavenProject/src/main/java/Util.java @@ -16,6 +16,22 @@ public static void print_mat(float[] mat, String name) { System.out.println(); } + public static void print_mat(double[] mat, String name) { + System.out.println(name + ": "); + System.out.print("Rank"); + for (int i = 0; i < Card.NUM_RANKS; i++) + System.out.print("\t" + Card.rankNames[i]); + for (int i = 0; i < Card.NUM_CARDS; i++) { + if (i % Card.NUM_RANKS == 0) + System.out.printf("\n%s", Card.suitNames[i / Card.NUM_RANKS]); + System.out.print("\t"); + System.out.printf("%1.1e", mat[i]); +// System.out.printf("%.4f", mat[i]); + } + System.out.println(); + System.out.println(); + } + public static void print_mat(boolean[] mat, String name) { System.out.println(name + ": "); System.out.print("Rank"); From ab41476a2c39a17df8e83bde35bda2d6a8079fb3 Mon Sep 17 00:00:00 2001 From: Tom-from-6520 Date: Mon, 27 Jul 2020 17:11:30 -0400 Subject: [PATCH 3/3] fixing gitignore --- ginrummy/GinRummyMavenProject/.gitignore | 4 ++++ .../src/main/java/HandEstimatorGeneral.java | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ginrummy/GinRummyMavenProject/.gitignore b/ginrummy/GinRummyMavenProject/.gitignore index b83d222..dabb0be 100644 --- a/ginrummy/GinRummyMavenProject/.gitignore +++ b/ginrummy/GinRummyMavenProject/.gitignore @@ -1 +1,5 @@ /target/ +.classpath +.gitignore +.project +.settings diff --git a/ginrummy/GinRummyMavenProject/src/main/java/HandEstimatorGeneral.java b/ginrummy/GinRummyMavenProject/src/main/java/HandEstimatorGeneral.java index 32ca660..1c14aa6 100644 --- a/ginrummy/GinRummyMavenProject/src/main/java/HandEstimatorGeneral.java +++ b/ginrummy/GinRummyMavenProject/src/main/java/HandEstimatorGeneral.java @@ -60,7 +60,4 @@ else if (a.get(0) > b.get(0)) // estimatedHand = hand; return hand; } - - - }