summaryrefslogtreecommitdiff
path: root/chapter14/organism.cxx
blob: 3a544d03cb6ed5a4b356e6bc5b91688ccb676730 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// FILE: organism.cxx
// CLASSES IMPLEMENTED:
//   organism, plant, animal, herbivore (see organism.h for documentation)
//
// INVARIANT for the organism class:
//   1. The member variable size contains the organism's size, in ounces.
//   2. The member variable rate contains the organism's growth rate, in
//      ounces per week.
//
// INVARIANT for the animal class:
//   1. The member variable need_each_week contains the organism's food
//      requirement, in ounces per week.
//   2. The member variable eaten_this_week contains the number of ounces of
//      food eaten by the organism in the current week.
//
// The plant and herbivore classes have no extra member variables, so there
// is no need for an invariant.

#include <cassert>    // Provides assert
#include "organism.h"

namespace main_savitch_14
{
    organism::organism(double init_size, double init_rate)
    {
	if (init_size == 0)
	    assert(init_rate == 0);
	else
	    assert(init_size >= 0);

	size = init_size;
	rate = init_rate;
    }
        
    void organism::alter_size(double amount)
    {
	size += amount;
	if (size <= 0)
	    death( );
    }

    void organism::death( )
    {
	size = rate = 0;
    }

    plant::plant(double init_size, double init_rate)
    : organism(init_size, init_rate)
    {
	// All work is done by the organism constructor
    }

    void plant::nibbled_on(double amount)
    // Library functions used: cassert
    {
	assert(amount >= 0);
	assert(amount <= get_size( ));
	alter_size(-amount);
    }

    animal::animal(double init_size, double init_rate, double init_need)
    : organism(init_size, init_rate)
    // Library facilities used: cassert
    {
	assert(0 <= init_need);
	need_each_week = init_need;
	eaten_this_week = 0;
    }

    void animal::assign_need(double new_need)
    // Library facilities used: cassert
    {
	assert(new_need >= 0);
	need_each_week = new_need;
    }

    void animal::eat(double amount)
    // Library facilities used: cassert
    {
	assert(amount >= 0);
	eaten_this_week += amount;
    }

    void animal::simulate_week( )
    {
	organism::simulate_week( );
	if (eaten_this_week < need_each_week)
	    death( );
	eaten_this_week = 0;
    }

    double animal::still_need( ) const
    {
	if (eaten_this_week >= need_each_week)
	    return 0;
	else
	    return need_each_week - eaten_this_week;
    }
    
    herbivore::herbivore(double init_size, double init_rate, double init_need)
    : animal(init_size, init_rate, init_need)
    {
	// All work is done by the animal constructor
    }

    void herbivore::nibble(plant& meal)
    {
	const double PORTION = 0.5;  // Eat no more than this portion of plant
	const double MAX_FRACTION = 0.1; // Eat no more than this fraction of weekly need
	double amount; // How many ounces of the plant will be eaten

	// Set amount to some portion of the plant, but no more than a given
	// maximum fraction of the total weekly need, and no more than what the
	// herbivore still needs to eat this week.
	amount = PORTION * meal.get_size( );
	if (amount > MAX_FRACTION * total_need( ))
	    amount = MAX_FRACTION * total_need( );
	if (amount > still_need( ))
	    amount = still_need( );
	
	// Eat the plant
	eat(amount);
	meal.nibbled_on(amount);
    }
   
}