program GiocoDelleProbabilita;
(* author: Ferrara Lorenzo <email@lorenzoferrara.net>
   download: www.lorenzoferrara.net
   date: 19 ago 2002
   license: GPL ver 2
   *)

uses crt;

const n = 40;        (* n e' il numero dei contenitori *)
      palline = 400; (* sono il numero di palline che vogliamo far cadere *)

var contenitori: array[1..n] of integer; (* ad ogni indice e' associato un contenitore *)
    posizionecorrente : integer;
    i : integer;

(* procedure: CalcolaPosizione
   ---------------------------
   calcola in quale contenitore la pallina deve cadere attraverso
   una serie di random, uno per ogni livello. all'inizio viene calcolato
   l'indice del contenitore centrale, che poi viene dec o inc a seconda se
   la pallina cade verso sinistra o destra.
   ATTENZIONE: se n e' dispari allora il dec o inc avvengonoe solo ogni due
               random. se n e' pari, allora avvengono ogni due random fino
               al penultimo e ancora una volta all'ultimo random.*)
procedure CalcolaPosizione;
var i: integer;
    dxsx1: integer;
    dxsx2: integer;
begin
  if ((n mod 2) <> 0) then        (* se n e' dispari *)
  begin
    posizionecorrente := (n div 2)+1;  (* calcolo dell'indice del contenitore centrale *)
    for i:=1 to ((n-1) div 2) do
    begin
      dxsx1 := random(2);
      dxsx2 := random(2);
      if ((dxsx1 = 0) and (dxsx2 = 0)) then dec(posizionecorrente);
      if ((dxsx1 = 1) and (dxsx2 = 1)) then inc(posizionecorrente);
    end;
    inc(contenitori[posizionecorrente]);
  end;

  if ((n mod 2) = 0) then         (* se n Š pari *)
  begin
    posizionecorrente := ((n div 2)+random(2)); (* calcolo dell'indice del contenitore centrale, *)
    for i:=1 to (n-2) do                        (* poiche' i contenitori sono pari, non si puo' stabilire un   *)
    begin                                       (* contenitore perfettamente centrale percio' di usa il random *)
      dxsx1 := random(2);                       (* se n = 4 il contenitore centrale puo' essere 2 oppure 3     *)
      dxsx2 := random(2);
      if ((dxsx1 = 0) and (dxsx2 = 0)) then dec(posizionecorrente);
      if ((dxsx1 = 1) and (dxsx2 = 1)) then inc(posizionecorrente);
    end;                                        (* il dec o inc avvengono solo ogni due random fino alla penultima*)
    dxsx1 := random(2);                         (* riga, ed ancora una volta all'ultima riga. fare il disegno con *)
    if (dxsx1 = 0) then dec(posizionecorrente); (* n pari per capire meglio *)
    if (dxsx1 = 1) then inc(posizionecorrente);
    inc(contenitori[posizionecorrente]);
  end;
end;

(* procedure: Azzera
   ----------------
   svuota tutti i contenitori, rappresentati da un array di interi. ogni
   unita' associata ad un indice i dell'array, e' una pallina che cade
   nel contenitore di incide i. *)
procedure Azzera;
var i : integer;
begin
  for i:=1 to n do
  begin
    contenitori[i] := 0;
  end;
end;

(* procedure: VisualizzaContenitori
   -------------------------------
   stampa un asterisco per ogni pallina caduta nel i-esimo contenitore.
   la procedura puo' essere chiamata in qualsiasi momento per osservare
   lo stato attuale dei contenitori. *)
procedure VisualizzaContenitori;
var i, j : integer;
begin
  for i:=1 to n do
  begin
    write('Contenitore ');
    if (i < 10) then write(' ');
    write(i);
    write(': ');
    if (contenitori[i] < 10) then write(' ');
    write(contenitori[i]);
    write(' ');
    for j:=1 to contenitori[i] do
    begin
      write('*');
    end;
    writeln;
  end;

end;

begin
  randomize;
  clrscr;
  writeln('Il gioco delle probabilita''');
  Azzera;
  for i:=1 to palline do
  begin
    CalcolaPosizione;
  end;
  VisualizzaContenitori;
  readln;
end.
