import java.awt.*; import java.applet.Applet; import java.applet.*; import java.text.NumberFormat; import java.lang.String; import java.lang.Integer; import java.lang.Double; import java.lang.Thread; import DiceStuff; /* ** When you create a new applet in Codewarrior Java, it is named "TrivialApplet" ** Never did get around to changing the name.... */ public class TrivialApplet extends Applet { /* ** Public declarations, mostly display objects, to ** be shared by all routines in the Applet. ** Each item that shows up on the applet display is defined here. */ Button Allbutton ; Button singlebutton ; Checkbox verbosebox ; TextField count1 ; TextField sides1 ; TextField tohit1 ; TextArea outfield ; /* ** Initilization */ public void init() { /* ** Set the applet panel to white. ** All children of the panel will also therefore be white. */ this.setBackground(Color.white) ; /* ** Put stuff on the penel left to right, top to bottom. */ this.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10)); /* ** Button to trigger complete sweep of all ** numbers that might be rolled. */ Allbutton = new Button("All") ; Allbutton.setBackground(Color.yellow) ; this.add(Allbutton) ; /* ** Button to generate stats for a single number. */ singlebutton = new Button("Single") ; singlebutton.setBackground(Color.yellow) ; this.add(singlebutton) ; /* ** Label and text field for the number of dice involved. */ Label number_label = new Label("Number") ; number_label.setBackground(Color.black) ; number_label.setForeground(Color.white) ; this.add("Number", number_label) ; count1 = new TextField("3", 5) ; count1.setFont(new Font("MonoSpaced", Font.PLAIN, 12)); count1.setEditable(true); this.add("Count1", count1) ; /* ** Label and text for the number of sides on the dice. */ Label sides_label = new Label("Sides") ; sides_label.setBackground(Color.black) ; sides_label.setForeground(Color.white) ; this.add("Sides", sides_label) ; sides1 = new TextField("6", 5) ; sides1.setFont(new Font("MonoSpaced", Font.PLAIN, 12)); sides1.setEditable(true); this.add("Sides1", sides1) ; /* ** Label and text for the target number of a single call. */ Label target_label = new Label("Target") ; target_label.setBackground(Color.black) ; target_label.setForeground(Color.white) ; this.add("Target", target_label) ; tohit1 = new TextField("11", 5) ; tohit1.setFont(new Font("MonoSpaced", Font.PLAIN, 12)); tohit1.setEditable(true); this.add("ToHit1", tohit1) ; /* ** Big scrolling place to return output to user. */ outfield = new TextArea("", 15, 50) ; outfield.setFont(new Font("MonoSpaced", Font.PLAIN, 12)) ; outfield.setEditable(true) ; this.add("Outfield", outfield) ; /* ** Place verbose checkbox. */ verbosebox = new Checkbox("Verbose") ; verbosebox.setBackground(Color.black) ; verbosebox.setForeground(Color.green) ; this.add("Verbose", verbosebox) ; /* ** Have vervose checked at start up time. */ verbosebox.setState(true) ; /* ** Request keyboard focus... cause the example in the book does. */ this.requestFocus() ; } // end of init /* ** Using Java 1.0 event model. ** Over ride action method. ** This routine is called whenever an "action" takes place. ** This includes buttons being pressed, and check boxes being ** toggled. Note, we take no action on a check box hit. ** Returning false results in the default checkbox routine ** running. */ public boolean action(Event e, Object arg) { // Assume event not handled until handeled. boolean event_handled = false ; if (e.target == singlebutton) { SingleButtonPress() ; event_handled = true ; } else if (e.target == Allbutton) { ClearButtonPress() ; event_handled = true ; } return event_handled ; } /* ** Not doing anything with main, but do we need ** to declare a main anyway? I don't know that ** a main entry point is necessary. All our active ** processing is done in response to buttons, but ** applets are supposed to have a main entry point. */ public static void main(String args[]) { boolean done = false ; /* Do forever. */ while (!done) { try { /* Do nothing for a second. */ Thread.sleep(1000) ; } catch (Exception e) { /* ** Don't really care if interrupted. ** Compiler yells at me if I don't catch ** the exception, however. */ } } } /* ** Reads and validates TextField inputs from the operator. ** Textfield must contain a valid integer, and the integer ** must be within a given range. If operator inserts invalid ** entries, a valid content is inserted, and a warning given. */ public int ReadValidateText( TextField field_in, int min_value, int max_value, String field_description) { String tempstring ; int tempint ; /* Read a string from the operator. */ tempstring = field_in.getText() ; try { /* Attempt to convert string into integer. */ tempint = Integer.parseInt(tempstring) ; if (tempint > max_value) { /* Integer too big. Override with max. */ tempint = max_value ; tempstring = (field_description + " overflow\n") ; outfield.appendText(tempstring) ; field_in.setText("" + tempint) ; } else if (tempint < min_value) { /* Integer too small. Override with min. */ tempint = min_value ; tempstring = (field_description + " underflow\n") ; outfield.appendText(tempstring) ; field_in.setText("" + tempint) ; } } catch (NumberFormatException ev) { /* Format exception. Not a valid integer. Override with min. */ tempint = min_value ; tempstring = (field_description + " bad integer format\n") ; outfield.appendText(tempstring) ; field_in.setText("" + tempint) ; } return tempint ; } /* ** The single button was pressed. ** Generate statistics for a single number. */ public void SingleButtonPress() { String tempholder ; int number_of_dice ; int sides_on_dice ; int target_to_roll ; long ways_to_roll ; /* ** Read and validate number of dice, sides, and number to be rolled. */ number_of_dice = ReadValidateText(count1, 1, DiceStuff.max_dice, "Number of Dice ") ; sides_on_dice = ReadValidateText(sides1, 2, DiceStuff.max_sides, "Sides on Dice ") ; target_to_roll = ReadValidateText(tohit1, 1, DiceStuff.max_roll, "Target to hit ") ; /* ** Display the result. */ dumpResult(number_of_dice, sides_on_dice, target_to_roll) ; /* ** Increment target. */ tohit1.setText(Integer.toString(target_to_roll + 1)) ; } /* ** This class sends a line to the outfield ** which gives information about one particular roll. */ public void dumpResult(int count, int sides, int target) { float chance_target_exact ; float chance_target_or_less ; float float_ways ; float float_sum ; float float_all ; String tempstring ; /* ** Invoke DiceStuff class. */ DiceStuff dice = new DiceStuff() ; /* ** Initialize text format object for long integers. */ NumberFormat bigformat = NumberFormat.getInstance() ; bigformat.setParseIntegerOnly(true) ; bigformat.setGroupingUsed(true) ; /* ** Initialize text format object for percentiles. */ NumberFormat percent = NumberFormat.getPercentInstance() ; percent.setMaximumFractionDigits(2) ; percent.setMinimumFractionDigits(0) ; /* Ways to roll this number */ long ways_to_roll = dice.intwayray(count, sides, target) ; /* ** Are we outputting everything? ** Read the verbose checkbox. */ if (verbosebox.getState()) { /* Ways to roll this number or lower. */ long sum_of_rolls = dice.sumwayray(count, sides, target) ; /* Possible ways for the dice to fall. */ long all_ways = dice.sumwayray(count, sides, count * sides) ; /* Convert everything to floating point format. */ float_ways = ways_to_roll ; float_sum = sum_of_rolls ; float_all = all_ways ; /* Percent chance of hitting this number exact. */ chance_target_exact = (float_ways / float_all) ; /* Percent chance of hitting this number or lower. */ chance_target_or_less = (float_sum / float_all) ; /* Write verbose to the output field. */ outfield.appendText(bigformat.format(ways_to_roll) + " ways to roll " + target + " on " + count + "D" + sides + " "+ percent.format(chance_target_exact) + " " + percent.format(chance_target_or_less) + "\n") ; } else { /* Write not at all verbose to the output field. */ outfield.appendText(ways_to_roll + "\n") ; } return ; } /* ** Called when the All Button is pressed. ** Generates statistics for all possible rolls. */ public void ClearButtonPress() { String tempholder ; int number_of_dice ; int sides_on_dice ; int target_to_roll ; /* ** Read and validate number of dice, sides. ** Target field is not used. */ number_of_dice = ReadValidateText(count1, 1, 15, "Number of Dice ") ; sides_on_dice = ReadValidateText(sides1, 2, DiceStuff.max_sides, "Sides on Dice ") ; /* ** Loop through each number that could be rolled. */ for (target_to_roll = number_of_dice ; target_to_roll <= (number_of_dice * sides_on_dice) ; target_to_roll++ ) { /* ** Display results for this number. */ dumpResult(number_of_dice, sides_on_dice, target_to_roll) ; } } /* ** Paint is called once at start and each time ** window is resized, exposed, etc... ** While the applet is created as white, the paint ** procedure draws a black rectangle over the ** exposed area of the applet. */ public void paint( Graphics g ) { g.setColor(Color.black) ; g.fillRect(0, 0, 500, 600) ; g.setColor(Color.white) ; } }