******************************************************************
COME GESTIRE I CONTENITORI 
(tratto dall'articolo sulla programmazione in Inform di Giancarlo 
Niccolai, apparsi sul numero 1 di Terra d'IF)
http://www.robertograssi.net/at/terradif.asp
*******************************************************************

Un importante prerequisito: questi articoli sono riservati a coloro che già 
conoscono le basi della programmazione inform. Per i principianti di Inform 
consigliamo i seguenti siti:

	Guida a Inform per Principianti (GIP):
	http://www.inform-italia.org/docs/gip/
	Un manuale su Inform:
	http://www.casalengo.it/vscarpa/inform/manuale/


I contenitori sono infinita fonte di gioie e dolori di tutti i programmatori
Inform. Sono molto divertenti da programmare e da utilizzare, e sembrano 
essere anche abbastanza elementari, ma in realtà scrivere un buon contenitore 
richiede una certa dose di abilità e attenzione.
Avete mai provato a mettere una spada lunga un metro e mezzo in una scatola 
di trenta centimetri di lato? Se non specificate cosa può entrare in un 
contenitore e cosa no, inform accetterà che il giocatore inserisca qualunque 
oggetto in esso, con risultati piuttosto spiacevoli.
In questo numero vedremo come "caratterizzare" un contenitore in modo che sia 
abbastanza "intelligente", capendo cosa può contenere e cosa no.

L'azione "Receive"
Ogni contenitore nel quale viene inserito un oggetto ha l'opportunità di dire 
la propria sull'azione compiuta dal giocatore; esso è infatti soggetto alla 
"Fake Action" (azione fasulla) "Receive". L'azione Receive è detta Fake Action 
perché non è generata dal giocatore (il quale genera un’azione sull'oggetto che 
viene INSERITO nel contenitore); essa è generata dal parser, che chiede 
all'oggetto contenitore di dire la propria su ciò che sta per accadere. Se la 
routine "before" del contenitore torna il valore "true" (diverso da zero), 
allora non accade altro; se torna "false" (o zero), il parser chiama la before 
dell'oggetto, e quindi inserisce l'oggetto nel contenitore. 
Esiste una proprietà generica chiamata "capacity"; le librerie di inform usano 
questa proprietà come "limite massimo" di oggetti che un contenitore può accettare. 
Quindi, normalmente, se date ad un contenitore una capacity pari a 2, potrete 
inserire solo due oggetti in esso.
Ridefiniremo la capacity in modo che tenga in considerazione la dimensione degli 
oggetti che vi devono essere introdotti. Per fare questo, aggiungeremo una proprietà 
chiamata "size", che indica la dimensione degli oggetti in "unità di ingombro". 
La dimensione di un’unità di ingombro sarà arbitraria; dovremo fare in modo che 
sia abbastanza "granulare" da prendere in considerazione in maniera abbastanza 
realistica tutti gli oggetti presenti nel nostro gioco.
Un contenitore intelligente accetterà oggetti fino a che la sua capacità glielo 
consentirà. Se un oggetto non ha la proprietà "size", supporremo che sia troppo 
grande per essere inserito in un contenitore. L'utente dovrebbe essere avvisato di 
questi tre fatti:

L'oggetto appena inserito ha quasi finito di riempire il contenitore. 
L'oggetto non può essere inserito nel contenitore perché non c'é più spazio 
L'oggetto è troppo grande per il contenitore (non potrebbe essere messo dentro 
nemmeno se il contenitore fosse vuoto). 


Il codice (commentato)
! ecco una classe che incapsula il comportamento di un contenitore
! intelligente.
Class SmartContainer
with
   capacity 0, !forziamo le istanze a dichiarare una capacity
   carried 0, ! la quantità di ingombro che stiamo trasportando
   before [;
      Receive:
         ! l'oggetto che sto ricevendo è il 'nome' dell'azione
         ! Se tale oggetto è troppo grande...
         if ( (~~ (noun provides size )) || noun.size > self.capacity ) {
            print (The) noun, " @`e troppo grande per entrare ", (artin) self,".^";
            rtrue; ! l'azione si ferma qui. Non c'è altro da fare.
         }
         else if ( self.capacity < self.carried + noun.size ) {
            print (The) self, " @`e quasi pien",(GenderAndNumber) self ,
                  " e ", (the) noun, " non ci sta proprio.^";
            rtrue;
         }
         else { ! ok, possiamo ricever l'oggetto
            self.carried = self.carried + noun.size;
            move noun to self;
            "Fatto."; ! Vedi nota (32)
         }

      LetGo: ! quando un oggetto viene preso
         if (noun provides size ) { ! meglio eseguire sempre un controllo
            self.carried = self.carried - noun.size ;
            rfalse;
         }
   ],
   has container openable;

Un esempio
Questo codice di esempio dimostra come usare il nostro contenitore intelligente. 



!--------------------------------------------------------
! Dimostrazione di SmartContainer
!--------------------------------------------------------

! libreria di inform
include "parser";
include "verblib";

! replace di infit
include "replace";

!
! Inserire qui la definizione di SmartContainer
!

Object room "La stanza"
with
description "Una stanza dimostrativa con qualche piccolo oggetto
   ed un contenitore ~furbo~."
   has light;


Object -> coin1 "moneta piccola"
with
   name 'moneta' 'piccola',
   size 1,
   description "Una graziosa moneta doratra. Probabilmente, oro falso.
      @`E molto leggera...",
   has female;


Object -> coin2 "moneta media"
with
   name 'moneta' 'media',
   size 2,
   description "Una graziosa moneta dorata. Sta comodamente in un palmo.",
   has female;


Object -> coin3 "moneta grande"
with
   name 'moneta' 'grande',
   size 3,
   description "Una moneta dorata graziosa, ma molto grande.
       Riempie tutto il palmo.",
   has female;


Object -> stone "grande pietra"
with
   name 'pietra' 'grande',
   size 10,
   description "Una pietra pesante, grossa come un pugno.",
   has female;

SmartContainer -> "scatoletta"
with
   name 'scatola' 'piccola' 'scatoletta',
   capacity 4,
   description "Una scatola nera, piuttosto piccola.",
   has open female;


[ Initialise;
   location = room;
];

! grammatica di italiana per inform
include "ItalianG";







