-- $Date: 2004/02/23 08:23:02 $
-- $Revision: 1.4 $
-- $Author: jcrocholl $

with Ada.Exceptions; use Ada.Exceptions;

package body Choices is

   -- Create a choice from scratch.
   function Create
     (Regular_Size : in Natural := Default_Regular_Size;
      Special_Size : in Natural := Default_Special_Size)
     return Choice_Access -- The newly created choice.
   is
      Result : Choice_Access := new Choice(Regular_Size, Special_Size);
   begin
      Reset(Result.Gen);
      return Result;
   end Create;

   --------------------------------
   -- Regular and special accessors
   --------------------------------

   -- Add a regular glyph to a choice.
   procedure Add_Regular
     (This : access Choice;      -- Add to this choice.
      Add  : in Glyph_Access) is -- Add this glyph.
   begin
      This.Regular_Count := This.Regular_Count + 1;
      This.Regular(This.Regular_Count) := Add;
   end Add_Regular;

   -- Get a specific glyph from a choice.
   function Get_Regular
     (This  : access Choice-- Get from this choice.
      Index : in Positive)   -- Index of the glyph.
     return Glyph_Access is  -- The glyph that has been chosen.
   begin
      return This.Regular(Index);
   end Get_Regular;

   -- Add a special glyph to a choice.
   procedure Add_Special
     (This : access Choice;      -- Add to this choice.
      Add  : in Glyph_Access) is -- Add this glyph.
   begin
      This.Special_Count := This.Special_Count + 1;
      This.Special(This.Special_Count) := Add;
   end Add_Special;

   -- Get a specific glyph from a choice.
   function Get_Special
     (This  : access Choice-- Get from this choice.
      Index : in Positive)   -- Index of the glyph.
     return Glyph_Access is  -- The glyph that has been chosen.
   begin
      return This.Special(Index);
   end Get_Special;

   -- Randomly choose a glyph from a glyph array.
   function Choose
     (From  : in Glyph_Array-- Choose from these glyphs.
      Count : in Positive;    -- Maximum choice index.
      Gen   : in Generator)   -- Use this random generator.
     return Glyph_Access is   -- The glyph that has been chosen.
   begin
      return From(1 + Natural(Real'Floor(Real(Random(Gen)) * Real(Count))));
   end Choose;

   -- Randomly choose a regular glyph from a choice.
   function Choose_Regular
     (This : access Choice-- Choose from this choice.
     return Glyph_Access is -- The glyph that has been chosen.
   begin
      return Choose(This.Regular, This.Regular_Count, This.Gen);
   end Choose_Regular;

   -- Randomly choose a special glyph from a choice.
   function Choose_Special
     (This : access Choice-- Choose from this choice.
     return Glyph_Access is -- The glyph that has been chosen.
   begin
      return Choose(This.Special, This.Special_Count, This.Gen);
   end Choose_Special;

   -- Randomly choose a glyph from a choice.
   -- Raises No_Glyphs_To_Choose_From if choice is empty.
   function Choose
     (This    : access Choice-- Choose from this choice.
      Special : in Percent)    -- How many special glyphs?
     return Glyph_Access is    -- The glyph that has been chosen.
   begin
      if This.Regular_Count > 0 then
         if This.Special_Count > 0 then
            if Real(Random(This.Gen)) < Real(Special) / 100.0
            then return Choose_Special(This);
            else return Choose_Regular(This);
            end if;
         else
            return Choose_Regular(This);
         end if;
      elsif This.Special_Count > 0 then
         return Choose_Special(This);
      else
         Raise_Exception(No_Glyphs_To_Choose_From'Identity);
      end if;
   end Choose;

end Choices;