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