
Object subclass: #MeadowInhabitant
  instanceVariableNames: 
    'age location displayState '
  classVariableNames: ''
  poolDictionaries: '' !

MeadowInhabitant subclass: #Grass
  instanceVariableNames: 
    'lastEaten '
  classVariableNames: 
    'GrassIcon '
  poolDictionaries: '' !

MeadowInhabitant subclass: #MeadowAnimal
  instanceVariableNames: 
    'lastAte lifeExpectancy birthRate foodRequirement lastBirth dailyRange '
  classVariableNames: ''
  poolDictionaries: '' !

MeadowAnimal subclass: #Fox
  instanceVariableNames: ''
  classVariableNames: 
    'FoxIcon '
  poolDictionaries: '' !

MeadowAnimal subclass: #Rabbit
  instanceVariableNames: 
    'lastEaten '
  classVariableNames: 
    'RabbitIcon '
  poolDictionaries: '' !


!MeadowInhabitant class methods !

example1
"create and display various MeadowInhabitants"
" MeadowInhabitant example1 "
|rand meadow |
rand := Random new.
meadow := Meadow new.
meadow grasses.
meadow rabbits.
meadow foxes.
25 timesRepeat:[meadow grasses add: (Grass new displayAt:(rand next:720)@(rand next:340))].
5 timesRepeat:[meadow rabbits add: (Rabbit new displayAt:(rand next:720)@(rand next:340))].
meadow foxes add: (Fox new displayAt:(rand next:720)@(rand next:340)).! !


!MeadowInhabitant methods !

age
"return the value of age default = 0"
age isNil ifTrue: [self age: 0].
^age!

age: anInteger
"set the value of age to anInteger "
age := anInteger!

displayState
"return the value of displayState default true"
displayState isNil ifTrue:[self displayState: true].
^displayState!

displayState: aBoolean
"set the value of displayState to aBoolean"
displayState := aBoolean!

location
"return the value of location default 0@0"
location isNil ifTrue: [self location: 0@0].
^location!

location: aPoint
"set the value of location to aPoint"
location := aPoint min: (720@340).! !


!Grass class methods !

example
"display Icon at location"
" Grass example "
|rand|
rand := Random new.
10 timesRepeat:
[self icon displayAt: (rand next: 720)@(rand next: 340)].!

example1
"create instance of grass default displayState false
last eaten -3 age 0 and let it grow making
displayState = true"
" Grass example1 "
| gras |
gras := Grass new grow inspect!

icon
"return the GrassIcon"
^GrassIcon!

icon: aForm
"set the icon to be aForm"
GrassIcon := aForm! !


!Grass methods !

displayAt: aPoint
"display the receiver's icon at aPoint"
self icon displayAt: aPoint!

grow
"if displayState is false and it was last
eaten > 2 days ago, set displayState to true"
( self displayState not) &
    (( self age)-(self lastEaten) > 2) ifTrue:
        [self displayState: true]!

icon
"return the GrassIcon"
^GrassIcon!

lastEaten
"return the number of days since grass was
last eaten default = -3"
lastEaten isNil ifTrue: [self lastEaten: -3].
^lastEaten!

lastEaten: anInteger
"set the date grass was last eaten to anInteger"
lastEaten := anInteger! !


!MeadowAnimal class methods !

example
" MeadowAnimal example "
"create instance of fox & rabbit"
"let them give birth and die"
| fox  |
fox := Fox new displayState: true;
            lastBirth: -2;
             birthRate: 1;
            lastAte: -2;
            lifeExpectancy: 20;
             foodRequirement: 1;
            age: 0.
fox birth ifTrue:[fox lastBirth: 0].
fox death ifTrue:[fox displayState: false].
fox inspect.! !


!MeadowAnimal methods !

birth
"return true  if display status is true
and (age-lastBirth> birthRate) else false"
^((self displayState) &
((self age)-(self lastBirth)
            >(self birthRate)))!

birthRate: anInteger
"set the value for the animal's birth rate days/birth"
birthRate := anInteger!

death
"if (age> lifeExpectancy)
or age-lastAte>foodRequirement
or displayStatus = false
then return true, else false"
^((self age > self lifeExpectancy)
 |((self age - self lastAte) > self foodRequirement)
 | self displayState not)!

distanceTo: anObject
"return the distance from self to anObject"
|point distance guess|
point := self location - anObject location.
distance := (point dotProduct: point)sqrt.
^distance.!

lastAte
"return the day the animal last ate"
"default = 0"
lastAte isNil ifTrue:[self lastAte: 0].
^lastAte!

lastAte: anInteger
"set the age that animal last ate to anInteger"

lastAte := anInteger!

lastBirth
"return the age of animal at the last birth"
"default = 0"
lastBirth isNil ifTrue: [self lastBirth: 0].
^lastBirth!

lastBirth: anInteger
"set the age of animal at the last birth"

lastBirth := anInteger!

lifeExpectancy: anInteger
"set the value for the animal's life expectancy"
lifeExpectancy := anInteger!

locatePrey: aBag
"locate the nearest visible prey from a Bag"
"if distance to chosenPrey < dailyRange set prey displayState
 to false to indicate being eaten"
|distance minDistance capturedPrey|
minDistance := 999. "default"
capturedPrey := nil. "default"
aBag do:[:eachPrey | (eachPrey displayState)
    ifTrue: [distance := self distanceTo: eachPrey.
            (distance < minDistance)
        ifTrue: [minDistance := distance.
            capturedPrey := eachPrey]]].
^capturedPrey!

moveToPrey: anObject
"if distance < dailyRange change location to
 the location of the Prey and its displayState
 to false set captor's IV lastAte to its age"
"if distance > dailyRange change location to
location+(difference in locations)*dailyRange/distance"

| distance |
(anObject isNil) ifTrue:[^nil].
distance := (self location dotProduct: (anObject location)) sqrt.
(distance <= self dailyRange )
    ifTrue:[self location: anObject location.
            anObject displayState: false.
            anObject lastEaten: anObject age.
             self lastAte: self age]
    ifFalse:[self location:(self location
        +(self location - anObject location)*
        (self dailyRange ) // distance)]! !


!Fox class methods !

example
"display Icon at location"
" Fox example "
|fox|
fox := Fox new.
self icon displayAt: 100@100.!

icon
"return the FoxIcon"
^FoxIcon!

icon: aForm
"set the icon to be aForm"
FoxIcon := aForm! !


!Fox methods !

birthRate
"return the value of the birth rate"
"for a fox default = 1 per 5 days"
birthRate isNil ifTrue: [self birthRate: 5].
^birthRate!

dailyRange
"return the daily range of species default 2000"
 dailyRange isNil ifTrue: [self dailyRange: 2000].
^dailyRange!

dailyRange: anInteger
"set the daily Range to be anInteger"
dailyRange := anInteger.!

displayAt: aPoint
"display the receiver's  icon at aPoint"
self icon displayAt: aPoint!

foodRequirement
"return the number of days the animal can live
without food default = 2"
 foodRequirement isNil ifTrue:
    [self foodRequirement: 2].
^foodRequirement!

foodRequirement: anInteger
"set the number of days the animal can live
without food "
 foodRequirement := anInteger!

icon
"return the FoxIcon"
^FoxIcon!

lifeExpectancy
"return the value of life expectancy"
"for a fox default = 20 days"
lifeExpectancy isNil
    ifTrue: [self lifeExpectancy: 20].
^lifeExpectancy! !


!Rabbit class methods !

example
"display Icon at location"
" Rabbit example "
self icon displayAt: 120@100.
self inspect!

icon
"return the RabbitIcon"
^RabbitIcon!

icon: aForm
"set the icon to be aForm"
RabbitIcon := aForm! !


!Rabbit methods !

birthRate
"return the value of the birth rate"
"for a rabbit default = 1 per day"
birthRate isNil ifTrue: [self birthRate: 1].
^birthRate!

dailyRange
"return the daily range of species default 500"
dailyRange isNil ifTrue: [self dailyRange: 500].
^dailyRange!

dailyRange: anInteger
"set the daily Range to be anInteger"
dailyRange := anInteger.!

displayAt: aPoint
"display the receiver's icon at aPoint"
self icon displayAt: aPoint!

foodRequirement
"return the number of days the animal can live
without food default = 1"
foodRequirement isNil ifTrue:
    [self foodRequirement: 1].
^foodRequirement!

foodRequirement: anInteger
"set the number of days the animal can live
without food "
 foodRequirement := anInteger!

icon
"return the RabbitIcon"
^RabbitIcon!

lastEaten: aValue
        "Set the value of lastEaten."
    lastEaten := aValue!

lifeExpectancy
"return the value of life expectancy"
"for a rabbit default = 10 days"
lifeExpectancy isNil
    ifTrue: [self lifeExpectancy: 10].
^lifeExpectancy! !
