PageRenderTime 47ms CodeModel.GetById 39ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/tutorial/spread_illness.e

http://github.com/tybor/Liberty
Specman e | 331 lines | 291 code | 23 blank | 17 comment | 9 complexity | b25b036b2afaaa294c0fe87941fe288c MD5 | raw file
  1--
  2-- Originally written by Cyril ADRIAN and Antony LE LABOUSSE
  3--
  4class SPREAD_ILLNESS
  5   -- To compile type command : compile SPREAD_ILLNESS make
  6   --
  7   -- Also try Optimised version adding options "-boost -O2"
  8   --
  9
 10create {ANY}
 11   make
 12
 13feature {}
 14   world1, world2: ARRAY2[INTEGER_8]
 15
 16   empty: INTEGER_8 1
 17
 18   healthy: INTEGER_8 0
 19
 20   di: ARRAY[INTEGER_8]
 21      once
 22         Result := {ARRAY[INTEGER_8] 1, << -1, -1, -1, 0, 1, 1, 1, 0 >> }
 23      end
 24
 25   dj: ARRAY[INTEGER_8]
 26      once
 27         Result := {ARRAY[INTEGER_8] 1, << -1, 0, 1, 1, 1, 0, -1, -1 >> }
 28      end
 29
 30   error_msg: STRING "Error : do it again !%N"
 31
 32   yes_or_no (question: STRING; default_answer: BOOLEAN): BOOLEAN
 33      do
 34         io.put_string(question)
 35         io.put_string(once "(y/n)? ")
 36         if default_answer then
 37            io.put_string(once "[y]")
 38         else
 39            io.put_string(once "[n]")
 40         end
 41
 42         io.flush
 43         io.read_line
 44         io.last_string.to_lower
 45         if io.last_string.is_empty then
 46            Result := default_answer
 47         elseif io.last_string.first = 'y' then
 48            Result := True
 49         elseif io.last_string.first = 'n' then
 50         else
 51            Result := yes_or_no(question, default_answer)
 52         end
 53      end
 54
 55feature {}
 56   make
 57         -- Try to spreads an illness through a set of people.
 58      local
 59         day: INTEGER; fed_up: BOOLEAN
 60      do
 61         from
 62            day := 1
 63            first_day
 64         until
 65            fed_up
 66         loop
 67            io.put_string(once "Day #")
 68            io.put_integer(day)
 69            io.put_new_line
 70            display
 71            fed_up := yes_or_no("Exit spread_illness", False)
 72            day := day + 1
 73            next_day
 74         end
 75      end
 76
 77   first_day
 78         -- Create the world in the 1st day's state.
 79      local
 80         i, j: INTEGER; ill_state: INTEGER_8; ok: BOOLEAN
 81      do
 82         if yes_or_no("Default First World", True) then
 83            world1 := {ARRAY2[INTEGER_8] 1, 18, 1, 18, << 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 84                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 85                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 86                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 87                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 88                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 89                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 90                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 91                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1;
 92                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 93                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 94                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 95                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 96                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 97                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 98                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
 99                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
100                                                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 >> }
101         else
102            io.put_string(once "World size: ")
103            io.flush
104            io.read_integer
105            create world1.make(1, io.last_integer, 1, io.last_integer)
106            io.put_string(once "%Ne)mpty, i)ll with number of days, h)ealthy%N%N")
107            from
108               i := world1.lower1
109            until
110               i > world1.upper1
111            loop
112               from
113                  j := world1.lower2
114               until
115                  j > world1.upper2
116               loop
117                  from
118                     ok := False
119                  until
120                     ok
121                  loop
122                     io.put_string(once "State of [")
123                     io.put_integer(i)
124                     io.put_character(',')
125                     io.put_integer(j)
126                     io.put_string(once "] : ")
127                     io.flush
128                     io.read_word
129                     inspect
130                        io.last_string.first
131                     when 'E', 'e' then
132                        if io.last_string.count /= 1 then
133                           io.put_string(error_msg)
134                        else
135                           world1.put(empty, i, j)
136                           ok := True
137                        end
138                     when 'H', 'h' then
139                        if io.last_string.count /= 1 then
140                           io.put_string(error_msg)
141                        else
142                           world1.put(healthy, i, j)
143                           ok := True
144                        end
145                     when 'I', 'i' then
146                        ok := True
147                        io.flush
148                        io.read_integer
149                        ill_state := io.last_integer.to_integer_8
150                        ill_state := ill_state.max(1)
151                        ill_state := ill_state.min(4)
152                        world1.put(-ill_state, i, j)
153                     else
154                        io.put_string(error_msg)
155                     end
156                  end
157                  j := j + 1
158               end
159               i := i + 1
160            end
161         end
162         world2 := world1.twin
163      end
164
165   display
166         -- Displays current `world2'.
167      local
168         i, j: INTEGER
169      do
170         io.put_string(once "+-")
171         from
172            i := world1.lower1
173         until
174            i > world1.upper1
175         loop
176            io.put_string(once "--")
177            i := i + 1
178         end
179
180         io.put_string(once "+%N")
181         from
182            i := world1.lower1
183         until
184            i > world1.upper1
185         loop
186            io.put_string(once "| ")
187            from
188               j := world1.lower2
189            until
190               j > world1.upper2
191            loop
192               inspect
193                  world2.item(i, j)
194               when empty then
195                  io.put_character(' ')
196               when healthy then
197                  io.put_character('O')
198               else
199                  io.put_character((-world2.item(i, j)).digit)
200               end
201               io.put_character(' ')
202               j := j + 1
203            end
204
205            io.put_string(once "|%N")
206            i := i + 1
207         end
208
209         io.put_string(once "+-")
210         from
211            i := world1.lower1
212         until
213            i > world1.upper1
214         loop
215            io.put_string(once "--")
216            i := i + 1
217         end
218
219         io.put_string(once "+%N")
220      end
221
222   next_day
223         -- `world1' and `world2' are swapped.
224      local
225         i, j: INTEGER
226      do
227         world1.copy(world2)
228         from
229            i := world1.lower1
230         until
231            i > world1.upper1
232         loop
233            from
234               j := world1.lower2
235            until
236               j > world1.upper2
237            loop
238               inspect
239                  world1.item(i, j)
240               when empty then
241               when healthy then
242                  spread(i, j)
243               else
244                  cure_or_die(i, j)
245               end
246               j := j + 1
247            end
248            i := i + 1
249         end
250      end
251
252feature {}
253   cure_or_die (i, j: INTEGER)
254         -- When ill, inspects if must be death or more ill or cured.
255      do
256         inspect
257            -world1.item(i, j)
258         when 1 then
259            world2.put(-2, i, j)
260         when 2 then
261            die(i, j)
262         when 3 then
263            world2.put(-4, i, j)
264         when 4 then
265            world2.put(healthy, i, j)
266         end
267      end
268
269   die (i, j: INTEGER)
270         -- When two days ill, dies or more ill ?
271      local
272         d, k: INTEGER
273      do
274         from
275            d := 1
276         variant
277            9 - d
278         until
279            d > 8
280         loop
281            if v(i + di.item(d), j + dj.item(d)) <= -2 then
282               k := k + 1
283            end
284            d := d + 1
285         end
286         if k >= 4 then
287            world2.put(empty, i, j)
288         else
289            world2.put(-3, i, j)
290         end
291      end
292
293   spread (i, j: INTEGER)
294         -- spread the illness ?
295      local
296         d: INTEGER
297      do
298         from
299            d := 1
300         variant
301            10 - d
302         until
303            d = 9
304         loop
305            if ill(i + di @ d, j + dj @ d) then
306               world2.put(-1, i, j)
307               d := 9
308            else
309               d := d + 1
310            end
311         end
312      end
313
314   ill (i, j: INTEGER): BOOLEAN
315         -- Is there someone is ill at `i', `j'.
316      do
317         Result := v(i, j) < 0
318      end
319
320   v (i, j: INTEGER): INTEGER
321         -- Gives `empty' when out of range or the
322         -- value in `world1'
323      do
324         if world1.lower1 <= i and then i <= world1.upper1 and (world1.lower2 <= j and then j <= world1.upper2) then
325            Result := world1.item(i, j)
326         else
327            Result := empty
328         end
329      end
330
331end -- class SPREAD_ILLNESS