shoes 4.0.0.pre2 → 4.0.0.pre3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +32 -21
  3. metadata +18 -337
  4. data/CHANGELOG +0 -84
  5. data/Gemfile +0 -24
  6. data/Guardfile +0 -11
  7. data/Rakefile +0 -14
  8. data/app.yaml +0 -60
  9. data/benchmark/app_clear.rb +0 -21
  10. data/benchmark/clear.rb +0 -69
  11. data/benchmark/memory/text_dispose.rb +0 -9
  12. data/benchmark/para_creator.rb +0 -9
  13. data/benchmark/paras.rb +0 -52
  14. data/benchmark/urls.rb +0 -40
  15. data/bin/ruby-shoes +0 -6
  16. data/bin/shoes-guard +0 -8
  17. data/bin/shoes-stub +0 -59
  18. data/ext/install/Rakefile +0 -29
  19. data/ext/install/shoes.bat +0 -9
  20. data/lib/shoes.rb +0 -5
  21. data/lib/shoes/ui/cli.rb +0 -102
  22. data/lib/shoes/ui/help.rb +0 -535
  23. data/lib/shoes/ui/manual.rb +0 -6
  24. data/lib/shoes/version.rb +0 -3
  25. data/manifests/common.rb +0 -34
  26. data/manifests/shoes.rb +0 -44
  27. data/samples/Gemfile +0 -3
  28. data/samples/Gemfile.lock +0 -35
  29. data/samples/README +0 -97
  30. data/samples/boom.rb +0 -239
  31. data/samples/class-book-adjusted.rb +0 -45
  32. data/samples/class-book.rb +0 -43
  33. data/samples/class-book.yaml +0 -387
  34. data/samples/clicky.rb +0 -24
  35. data/samples/cy.png +0 -0
  36. data/samples/expert-definr.rb +0 -23
  37. data/samples/expert-funnies.rb +0 -60
  38. data/samples/expert-game-of-life-adjusted.rb +0 -249
  39. data/samples/expert-game-of-life.rb +0 -243
  40. data/samples/expert-irb-adjusted.rb +0 -110
  41. data/samples/expert-irb.rb +0 -112
  42. data/samples/expert-minesweeper-adjusted.rb +0 -272
  43. data/samples/expert-minesweeper.rb +0 -267
  44. data/samples/expert-othello-adjusted.rb +0 -325
  45. data/samples/expert-othello.rb +0 -318
  46. data/samples/expert-pong.rb +0 -62
  47. data/samples/expert-snake.rb +0 -78
  48. data/samples/expert-tankspank.rb +0 -385
  49. data/samples/flow.rb +0 -63
  50. data/samples/good-arc.rb +0 -45
  51. data/samples/good-clock.rb +0 -51
  52. data/samples/good-displace.rb +0 -98
  53. data/samples/good-follow.rb +0 -26
  54. data/samples/good-potato-chopping.rb +0 -22
  55. data/samples/good-reminder.rb +0 -174
  56. data/samples/good-vjot.rb +0 -58
  57. data/samples/gray.rb +0 -11
  58. data/samples/loogink.png +0 -0
  59. data/samples/nks_booklist.rb +0 -24
  60. data/samples/nks_breadsticks.rb +0 -7
  61. data/samples/nks_dancing_circle.rb +0 -13
  62. data/samples/nks_dictionary.rb +0 -23
  63. data/samples/nks_edit_box.rb +0 -4
  64. data/samples/nks_edit_line.rb +0 -6
  65. data/samples/nks_notes.rb +0 -16
  66. data/samples/nks_poem.rb +0 -22
  67. data/samples/nks_self.rb +0 -6
  68. data/samples/nks_text_sizes.rb +0 -10
  69. data/samples/nks_trurl.rb +0 -5
  70. data/samples/original-manual-adjusted.rb +0 -475
  71. data/samples/original-manual.rb +0 -472
  72. data/samples/packaging/package_me.rb +0 -6
  73. data/samples/potato_chopping/1258_s001.gif +0 -0
  74. data/samples/potato_chopping/1258_s002.gif +0 -0
  75. data/samples/potato_chopping/1258_s003.gif +0 -0
  76. data/samples/potato_chopping/1258_s004.gif +0 -0
  77. data/samples/potato_chopping/1258_s005.gif +0 -0
  78. data/samples/potato_chopping/1258_s006.gif +0 -0
  79. data/samples/potato_chopping/1258_s007.gif +0 -0
  80. data/samples/potato_chopping/1258_s008.gif +0 -0
  81. data/samples/potato_chopping/1258_s009.gif +0 -0
  82. data/samples/potato_chopping/1258_s010.gif +0 -0
  83. data/samples/potato_chopping/1258_s011.gif +0 -0
  84. data/samples/potato_chopping/1258_s012.gif +0 -0
  85. data/samples/potato_chopping/1258_s013.gif +0 -0
  86. data/samples/potato_chopping/1258_s014.gif +0 -0
  87. data/samples/potato_chopping/1258_s015.gif +0 -0
  88. data/samples/potato_chopping/1258_s016.gif +0 -0
  89. data/samples/potato_chopping/1258_s017.gif +0 -0
  90. data/samples/potato_chopping/1258_s018.gif +0 -0
  91. data/samples/potato_chopping/1258_s019.gif +0 -0
  92. data/samples/potato_chopping/1258_s020.gif +0 -0
  93. data/samples/potato_chopping/1258_s021.gif +0 -0
  94. data/samples/potato_chopping/1258_s022.gif +0 -0
  95. data/samples/potato_chopping/1258_s023.gif +0 -0
  96. data/samples/potato_chopping/1258_s024.gif +0 -0
  97. data/samples/potato_chopping/1258_s025.gif +0 -0
  98. data/samples/potato_chopping/1258_s026.gif +0 -0
  99. data/samples/potato_chopping/1258_s027.gif +0 -0
  100. data/samples/potato_chopping/1258_s028.gif +0 -0
  101. data/samples/potato_chopping/1258_s029.gif +0 -0
  102. data/samples/potato_chopping/1258_s030.gif +0 -0
  103. data/samples/potato_chopping/1258_s031.gif +0 -0
  104. data/samples/potato_chopping/1258_s032.gif +0 -0
  105. data/samples/potato_chopping/1258_s033.gif +0 -0
  106. data/samples/potato_chopping/1258_s034.gif +0 -0
  107. data/samples/potato_chopping/1258_s035.gif +0 -0
  108. data/samples/potato_chopping/1258_s036.gif +0 -0
  109. data/samples/potato_chopping/1258_s037.gif +0 -0
  110. data/samples/potato_chopping/1258_s038.gif +0 -0
  111. data/samples/potato_chopping/1258_s039.gif +0 -0
  112. data/samples/potato_chopping/1258_s040.gif +0 -0
  113. data/samples/potato_chopping/1258_s041.gif +0 -0
  114. data/samples/potato_chopping/1258_s042.gif +0 -0
  115. data/samples/potato_chopping/1258_s043.gif +0 -0
  116. data/samples/potato_chopping/1258_s044.gif +0 -0
  117. data/samples/potato_chopping/1258_s045.gif +0 -0
  118. data/samples/potato_chopping/1258_s046.gif +0 -0
  119. data/samples/potato_chopping/1258_s047.gif +0 -0
  120. data/samples/potato_chopping/1258_s048.gif +0 -0
  121. data/samples/potato_chopping/1258_s049.gif +0 -0
  122. data/samples/potato_chopping/1258_s050.gif +0 -0
  123. data/samples/potato_chopping/1258_s051.gif +0 -0
  124. data/samples/potato_chopping/1258_s052.gif +0 -0
  125. data/samples/potato_chopping/1258_s053.gif +0 -0
  126. data/samples/potato_chopping/1258_s054.gif +0 -0
  127. data/samples/potato_chopping/1258_s055.gif +0 -0
  128. data/samples/potato_chopping/1258_s056.gif +0 -0
  129. data/samples/potato_chopping/1258_s057.gif +0 -0
  130. data/samples/potato_chopping/1258_s058.gif +0 -0
  131. data/samples/potato_chopping/1258_s059.gif +0 -0
  132. data/samples/present.rb +0 -27
  133. data/samples/progress.rb +0 -10
  134. data/samples/sample1.rb +0 -30
  135. data/samples/sample12.rb +0 -21
  136. data/samples/sample13.rb +0 -13
  137. data/samples/sample14.rb +0 -64
  138. data/samples/sample15.rb +0 -18
  139. data/samples/sample16.rb +0 -10
  140. data/samples/sample17.rb +0 -10
  141. data/samples/sample2.rb +0 -14
  142. data/samples/sample21.rb +0 -5
  143. data/samples/sample23.rb +0 -8
  144. data/samples/sample24.rb +0 -21
  145. data/samples/sample27.rb +0 -18
  146. data/samples/sample3.rb +0 -14
  147. data/samples/sample31.rb +0 -22
  148. data/samples/sample34.rb +0 -27
  149. data/samples/sample35.rb +0 -32
  150. data/samples/sample37.rb +0 -8
  151. data/samples/sample4.rb +0 -7
  152. data/samples/sample42.rb +0 -14
  153. data/samples/sample45.rb +0 -11
  154. data/samples/sample56.rb +0 -10
  155. data/samples/sample6.rb +0 -9
  156. data/samples/sample7.rb +0 -3
  157. data/samples/sample8.rb +0 -7
  158. data/samples/sample9.rb +0 -10
  159. data/samples/simple-accordion.rb +0 -75
  160. data/samples/simple-anim-shapes.rb +0 -17
  161. data/samples/simple-anim-text.rb +0 -13
  162. data/samples/simple-animate.rb +0 -12
  163. data/samples/simple-arc.rb +0 -23
  164. data/samples/simple-bounce.rb +0 -24
  165. data/samples/simple-brightness-transitions.rb +0 -8
  166. data/samples/simple-button-animate.rb +0 -16
  167. data/samples/simple-calc-2.rb +0 -34
  168. data/samples/simple-calc.rb +0 -70
  169. data/samples/simple-color-selector.rb +0 -10
  170. data/samples/simple-color-transitions.rb +0 -11
  171. data/samples/simple-control-sizes.rb +0 -24
  172. data/samples/simple-curve.rb +0 -26
  173. data/samples/simple-dialogs-outside.rb +0 -12
  174. data/samples/simple-dialogs.rb +0 -32
  175. data/samples/simple-displace.rb +0 -15
  176. data/samples/simple-downloader.rb +0 -27
  177. data/samples/simple-draw.rb +0 -13
  178. data/samples/simple-editor.rb +0 -28
  179. data/samples/simple-face.rb +0 -14
  180. data/samples/simple-flow-wrap.rb +0 -11
  181. data/samples/simple-font.rb +0 -17
  182. data/samples/simple-form.rb +0 -29
  183. data/samples/simple-form.shy +0 -0
  184. data/samples/simple-fullscreen.rb +0 -4
  185. data/samples/simple-guess-game.rb +0 -28
  186. data/samples/simple-keypress.rb +0 -14
  187. data/samples/simple-manual.rb +0 -2
  188. data/samples/simple-mask.rb +0 -21
  189. data/samples/simple-menu.rb +0 -47
  190. data/samples/simple-mouse-follow.rb +0 -8
  191. data/samples/simple-move.rb +0 -13
  192. data/samples/simple-oval.rb +0 -3
  193. data/samples/simple-sample-executor.rb +0 -6
  194. data/samples/simple-shoes-intro.rb +0 -22
  195. data/samples/simple-slide.rb +0 -56
  196. data/samples/simple-sound.rb +0 -30
  197. data/samples/simple-sphere.rb +0 -28
  198. data/samples/simple-stripes.rb +0 -8
  199. data/samples/simple-tictactoe.rb +0 -238
  200. data/samples/simple-timer.rb +0 -15
  201. data/samples/simple-video.rb +0 -13
  202. data/samples/simple-visibility.rb +0 -11
  203. data/samples/simple-widget.rb +0 -9
  204. data/samples/sounds/102719__sarge4267__explosion.mp3 +0 -0
  205. data/samples/sounds/145622__andybrannan__train-fog-horn-long-wyomming.aiff +0 -0
  206. data/samples/sounds/46492__phreaksaccount__shields1.ogg +0 -0
  207. data/samples/sounds/61847__simon-rue__boink-v3.wav +0 -0
  208. data/samples/swt-raw.rb +0 -20
  209. data/samples/troll.rb +0 -22
  210. data/shoes.gemspec +0 -29
  211. data/snapshots/sample1.png +0 -0
  212. data/snapshots/sample10.png +0 -0
  213. data/snapshots/sample11.png +0 -0
  214. data/snapshots/sample12.png +0 -0
  215. data/snapshots/sample13.png +0 -0
  216. data/snapshots/sample14.png +0 -0
  217. data/snapshots/sample15.png +0 -0
  218. data/snapshots/sample16.png +0 -0
  219. data/snapshots/sample17.png +0 -0
  220. data/snapshots/sample18.png +0 -0
  221. data/snapshots/sample19.png +0 -0
  222. data/snapshots/sample2.png +0 -0
  223. data/snapshots/sample20.png +0 -0
  224. data/snapshots/sample21.png +0 -0
  225. data/snapshots/sample22.png +0 -0
  226. data/snapshots/sample23.png +0 -0
  227. data/snapshots/sample24.png +0 -0
  228. data/snapshots/sample27.png +0 -0
  229. data/snapshots/sample28.png +0 -0
  230. data/snapshots/sample29.png +0 -0
  231. data/snapshots/sample3.png +0 -0
  232. data/snapshots/sample30.png +0 -0
  233. data/snapshots/sample31.png +0 -0
  234. data/snapshots/sample34.png +0 -0
  235. data/snapshots/sample35.png +0 -0
  236. data/snapshots/sample36.png +0 -0
  237. data/snapshots/sample37.png +0 -0
  238. data/snapshots/sample4.png +0 -0
  239. data/snapshots/sample42.png +0 -0
  240. data/snapshots/sample44.png +0 -0
  241. data/snapshots/sample45.png +0 -0
  242. data/snapshots/sample46.png +0 -0
  243. data/snapshots/sample5.png +0 -0
  244. data/snapshots/sample56.png +0 -0
  245. data/snapshots/sample6.png +0 -0
  246. data/snapshots/sample7.png +0 -0
  247. data/snapshots/sample8.png +0 -0
  248. data/snapshots/sample9.png +0 -0
  249. data/snapshots/sample99.png +0 -0
  250. data/static/PKGBUILD +0 -47
  251. data/static/Shoes.icns +0 -0
  252. data/static/avatar.png +0 -0
  253. data/static/code_highlighter.js +0 -188
  254. data/static/code_highlighter_ruby.js +0 -26
  255. data/static/downloading.png +0 -0
  256. data/static/icon-debug.png +0 -0
  257. data/static/icon-error.png +0 -0
  258. data/static/icon-info.png +0 -0
  259. data/static/icon-warn.png +0 -0
  260. data/static/listbox_button1.png +0 -0
  261. data/static/listbox_button2.png +0 -0
  262. data/static/man-app.png +0 -0
  263. data/static/man-builds.png +0 -0
  264. data/static/man-builds1.png +0 -0
  265. data/static/man-editor-notepad.png +0 -0
  266. data/static/man-editor-osx.png +0 -0
  267. data/static/man-ele-background.png +0 -0
  268. data/static/man-ele-border.png +0 -0
  269. data/static/man-ele-button.png +0 -0
  270. data/static/man-ele-check.png +0 -0
  271. data/static/man-ele-editbox.png +0 -0
  272. data/static/man-ele-editline.png +0 -0
  273. data/static/man-ele-image.png +0 -0
  274. data/static/man-ele-listbox.png +0 -0
  275. data/static/man-ele-progress.png +0 -0
  276. data/static/man-ele-radio.png +0 -0
  277. data/static/man-ele-shape.png +0 -0
  278. data/static/man-ele-textblock.png +0 -0
  279. data/static/man-ele-video.png +0 -0
  280. data/static/man-intro-dmg.png +0 -0
  281. data/static/man-intro-exe.png +0 -0
  282. data/static/man-look-tiger.png +0 -0
  283. data/static/man-look-ubuntu.png +0 -0
  284. data/static/man-look-vista.png +0 -0
  285. data/static/man-run-osx.png +0 -0
  286. data/static/man-run-vista.png +0 -0
  287. data/static/man-run-xp.png +0 -0
  288. data/static/man-shot1.png +0 -0
  289. data/static/manual-en.txt +0 -3531
  290. data/static/manual-ja.txt +0 -2829
  291. data/static/manual.css +0 -184
  292. data/static/menu-corner1.png +0 -0
  293. data/static/menu-corner2.png +0 -0
  294. data/static/menu-gray.png +0 -0
  295. data/static/menu-left.png +0 -0
  296. data/static/menu-right.png +0 -0
  297. data/static/menu-top.png +0 -0
  298. data/static/shoes-dmg.jpg +0 -0
  299. data/static/shoes-icon-blue.png +0 -0
  300. data/static/shoes-icon-brown.png +0 -0
  301. data/static/shoes-icon.png +0 -0
  302. data/static/shoes-manual-apps.gif +0 -0
  303. data/static/shoes-manual-apps.png +0 -0
  304. data/static/shoes_main_window.png +0 -0
  305. data/static/stripe.png +0 -0
  306. data/static/tutor-back.png +0 -0
  307. data/tasks/changelog.rb +0 -92
  308. data/tasks/gem.rb +0 -38
  309. data/tasks/rspec.rb +0 -106
  310. data/tasks/sample.rb +0 -66
  311. data/tasks/yard.rb +0 -13
@@ -1,110 +0,0 @@
1
- require 'irb/ruby-lex'
2
- require 'stringio'
3
-
4
- class MimickIRB < RubyLex
5
- attr_accessor :started
6
-
7
- class Continue < StandardError; end
8
- class Empty < StandardError; end
9
-
10
- def initialize
11
- super
12
- set_input(StringIO.new)
13
- end
14
-
15
- def run(str)
16
- obj = nil
17
- @io << str
18
- @io.rewind
19
- unless l = lex
20
- raise Empty if @line == ''
21
- else
22
- case l.strip
23
- when "reset"
24
- @line = ""
25
- when "time"
26
- @line = "puts %{You started \#{IRBalike.started.since} ago.}"
27
- else
28
- @line << l << "\n"
29
- if @ltype or @continue or @indent > 0
30
- raise Continue
31
- end
32
- end
33
- end
34
- unless @line.empty?
35
- obj = eval @line, TOPLEVEL_BINDING, "(irb)", @line_no
36
- end
37
- @line_no += @line.scan(/\n/).length
38
- @line = ''
39
- @exp_line_no = @line_no
40
-
41
- @indent = 0
42
- @indent_stack = []
43
-
44
- $stdout.rewind
45
- output = $stdout.read
46
- $stdout.truncate(0)
47
- $stdout.rewind
48
- [output, obj]
49
- rescue Object => e
50
- case e when Empty, Continue
51
- else @line = ""
52
- end
53
- raise e
54
- ensure
55
- set_input(StringIO.new)
56
- end
57
-
58
- end
59
-
60
- CURSOR = ">>"
61
- IRBalike = MimickIRB.new
62
- $stdout = StringIO.new
63
-
64
- Shoes.app do
65
- @str, @cmd = [CURSOR + " "], ""
66
- background "#555"
67
- @scroll = stack do
68
- background "#555"
69
- stack width: 1.0, height: 50 do
70
- para "Interactive Ruby ready.", fill: white, stroke: red
71
- end
72
- @console = para *@str, font: "Lucida Console", stroke: "#dfa"
73
- @console.cursor = -1
74
- end
75
- keypress do |k|
76
- case k
77
- when "\n"
78
- begin
79
- out, obj = IRBalike.run(@cmd + ';')
80
- @str += ["#@cmd\n",
81
- fg("#{out}=> #{obj.inspect}\n", "#fda"),
82
- "#{CURSOR} "]
83
- @cmd = ""
84
- rescue MimickIRB::Empty
85
- rescue MimickIRB::Continue
86
- @str += ["#@cmd\n.. "]
87
- @cmd = ""
88
- rescue Object => e
89
- @str += ["#@cmd\n", fg("#{e.class}: #{e.message}\n", "#fcf"),
90
- "#{CURSOR} "]
91
- @cmd = ""
92
- end
93
- when String
94
- @cmd += k
95
- when :backspace
96
- @cmd.slice!(-1)
97
- when :tab
98
- @cmd += " "
99
- when :alt_q
100
- exit
101
- when :alt_c
102
- self.clipboard = @cmd
103
- when :alt_v
104
- @cmd += self.clipboard
105
- end
106
- @console.replace *(@str + [@cmd])
107
- tmp = @scroll.height - app.height
108
- @scroll.scroll_top = tmp > 0 ? tmp : 0
109
- end
110
- end
@@ -1,112 +0,0 @@
1
- require 'irb/ruby-lex'
2
- require 'stringio'
3
-
4
- class MimickIRB < RubyLex
5
- attr_accessor :started
6
-
7
- class Continue < StandardError; end
8
- class Empty < StandardError; end
9
-
10
- def initialize
11
- super
12
- set_input(StringIO.new)
13
- end
14
-
15
- def run(str)
16
- obj = nil
17
- @io << str
18
- @io.rewind
19
- unless l = lex
20
- raise Empty if @line == ''
21
- else
22
- case l.strip
23
- when "reset"
24
- @line = ""
25
- when "time"
26
- @line = "puts %{You started \#{IRBalike.started.since} ago.}"
27
- else
28
- @line << l << "\n"
29
- if @ltype or @continue or @indent > 0
30
- raise Continue
31
- end
32
- end
33
- end
34
- unless @line.empty?
35
- obj = eval @line, TOPLEVEL_BINDING, "(irb)", @line_no
36
- end
37
- @line_no += @line.scan(/\n/).length
38
- @line = ''
39
- @exp_line_no = @line_no
40
-
41
- @indent = 0
42
- @indent_stack = []
43
-
44
- $stdout.rewind
45
- output = $stdout.read
46
- $stdout.truncate(0)
47
- $stdout.rewind
48
- [output, obj]
49
- rescue Object => e
50
- case e when Empty, Continue
51
- else @line = ""
52
- end
53
- raise e
54
- ensure
55
- set_input(StringIO.new)
56
- end
57
-
58
- end
59
-
60
- CURSOR = ">>"
61
- IRBalike = MimickIRB.new
62
- $stdout = StringIO.new
63
-
64
- Shoes.app do
65
- @str, @cmd = [CURSOR + " "], ""
66
- stack width: 1.0, height: 1.0 do
67
- background "#555"
68
- stack width: 1.0, height: 50 do
69
- para "Interactive Ruby ready.", fill: white, stroke: red
70
- end
71
- @scroll =
72
- stack width: 1.0, height: -50, scroll: true do
73
- background "#555"
74
- @console = para @str, font: "Monospace 12px", stroke: "#dfa"
75
- @console.cursor = -1
76
- end
77
- end
78
- keypress do |k|
79
- case k
80
- when "\n"
81
- begin
82
- out, obj = IRBalike.run(@cmd + ';')
83
- @str += ["#@cmd\n",
84
- span("#{out}=> #{obj.inspect}\n", stroke: "#fda"),
85
- "#{CURSOR} "]
86
- @cmd = ""
87
- rescue MimickIRB::Empty
88
- rescue MimickIRB::Continue
89
- @str += ["#@cmd\n.. "]
90
- @cmd = ""
91
- rescue Object => e
92
- @str += ["#@cmd\n", span("#{e.class}: #{e.message}\n", stroke: "#fcf"),
93
- "#{CURSOR} "]
94
- @cmd = ""
95
- end
96
- when String
97
- @cmd += k
98
- when :backspace
99
- @cmd.slice!(-1)
100
- when :tab
101
- @cmd += " "
102
- when :alt_q
103
- quit
104
- when :alt_c
105
- self.clipboard = @cmd
106
- when :alt_v
107
- @cmd += self.clipboard
108
- end
109
- @console.replace *(@str + [@cmd])
110
- @scroll.scroll_top = @scroll.scroll_max
111
- end
112
- end
@@ -1,272 +0,0 @@
1
- #
2
- # Shoes Minesweeper by que/varyform
3
- #
4
- LEVELS = { beginner: [9, 9, 10], intermediate: [16, 16, 40], expert: [30, 16, 99] }
5
-
6
- class Field
7
- CELL_SIZE = 20
8
- COLORS = %w(#00A #0A0 #A00 #004 #040 #400 #000)
9
-
10
- class Cell
11
- attr_accessor :flag
12
- def initialize(aflag = false)
13
- @flag = aflag
14
- end
15
- end
16
-
17
- class Bomb < Cell
18
- attr_accessor :exploded
19
- def initialize(exploded = false)
20
- @exploded = exploded
21
- end
22
- end
23
-
24
- class OpenCell < Cell
25
- attr_accessor :number
26
- def initialize(bombs_around = 0)
27
- @number = bombs_around
28
- end
29
- end
30
-
31
- class EmptyCell < Cell; end
32
-
33
- attr_reader :cell_size, :offset
34
-
35
- def initialize(app, level = :beginner)
36
- @app = app
37
- @field = []
38
- @w, @h, @bombs = LEVELS[level][0], LEVELS[level][1], LEVELS[level][2]
39
- @h.times { @field << Array.new(@w) { EmptyCell.new } }
40
- @game_over = false
41
- @width, @height, @cell_size = @w * CELL_SIZE, @h * CELL_SIZE, CELL_SIZE
42
- @offset = [(@app.width - @width.to_i) / 2, (@app.height - @height.to_i) / 2]
43
- plant_bombs
44
- @start_time = Time.now
45
- end
46
-
47
- def total_time
48
- @latest_time = Time.now - @start_time unless game_over? || all_found?
49
- @latest_time
50
- end
51
-
52
- def click!(x, y)
53
- return unless cell_exists?(x, y)
54
- return if has_flag?(x, y)
55
- return die!(x, y) if bomb?(x, y)
56
- open(x, y)
57
- discover(x, y) if bombs_around(x, y) == 0
58
- end
59
-
60
- def flag!(x, y)
61
- return unless cell_exists?(x, y)
62
- self[x, y].flag = !self[x, y].flag unless self[x, y].is_a?(OpenCell)
63
- end
64
-
65
- def game_over?
66
- @game_over
67
- end
68
-
69
- def render_cell(x, y, color = "#AAA", stroke = true)
70
- @app.stroke "#666" if stroke
71
- @app.fill color
72
- @app.rect $x+x*cell_size, $y+y*cell_size, cell_size-1, cell_size-1
73
- @app.stroke "#BBB" if stroke
74
- @app.line $x+x*cell_size+1, $y+y*cell_size+1, $x+x*cell_size+cell_size-1, $y+y*cell_size
75
- @app.line $x+x*cell_size+1, $y+y*cell_size+1, $x+x*cell_size, $y+y*cell_size+cell_size-1
76
- end
77
-
78
- def render_flag(x, y)
79
- @app.stroke "#000"
80
- @app.line($x+x*cell_size+cell_size / 4 + 1, $y+y*cell_size + cell_size / 5, $x+x*cell_size+cell_size / 4 + 1, $y+y*cell_size+cell_size / 5 * 4)
81
- @app.fill "#A00"
82
- @app.rect($x+x*cell_size+cell_size / 4+2, $y+y*cell_size + cell_size / 5,
83
- cell_size / 3, cell_size / 4)
84
- end
85
-
86
- def render_bomb(x, y)
87
- render_cell(x, y)
88
- if (game_over? or all_found?) then # draw bomb
89
- if self[x, y].exploded then
90
- render_cell(x, y, @app.rgb(0xFF, 0, 0, 0.5))
91
- end
92
- @app.nostroke
93
- @app.fill @app.rgb(0, 0, 0, 0.8)
94
- @app.oval($x+x*cell_size+3, $y+y*cell_size+3, 13)
95
- @app.fill "#333"
96
- @app.oval($x+x*cell_size+5, $y+y*cell_size+5, 7)
97
- @app.fill "#AAA"
98
- @app.oval($x+x*cell_size+6, $y+y*cell_size+6, 3)
99
- @app.fill @app.rgb(0, 0, 0, 0.8)
100
- @app.stroke "#222"
101
- @app.strokewidth 2
102
- @app.oval($x+x*cell_size + cell_size / 2 + 2, $y+y*cell_size + cell_size / 4 - 2, 2)
103
- @app.oval($x+x*cell_size + cell_size / 2 + 4, $y+y*cell_size + cell_size / 4 - 2, 1)
104
- @app.strokewidth 1
105
- end
106
- end
107
-
108
- def render_number(x, y)
109
- render_cell(x, y, "#999", false)
110
- if self[x, y].number != 0 then
111
- @app.nostroke
112
- @app.nofill
113
- @app.oval($x+x*cell_size + 3, $y+y*cell_size - 2, 10)
114
- @app.para self[x, y].number.to_s, left: $x+x*cell_size + 3, top: $y+y*cell_size - 2,
115
- size: 13, stroke: COLORS[self[x, y].number - 1]
116
- end
117
- end
118
-
119
- def paint
120
- 0.upto @h-1 do |y|
121
- 0.upto @w-1 do |x|
122
- @app.nostroke
123
- case self[x, y]
124
- when EmptyCell then render_cell(x, y)
125
- when Bomb then render_bomb(x, y)
126
- when OpenCell then render_number(x, y)
127
- end
128
- render_flag(x, y) if has_flag?(x, y) && !(game_over? && bomb?(x, y))
129
- end
130
- end
131
- end
132
-
133
- def bombs_left
134
- @bombs - @field.flatten.compact.reject {|e| !e.flag }.size
135
- end
136
-
137
- def all_found?
138
- @field.flatten.compact.reject {|e| !e.is_a?(OpenCell) }.size + @bombs == @w*@h
139
- end
140
-
141
- def reveal!(x, y)
142
- return unless cell_exists?(x, y)
143
- return unless self[x, y].is_a?(Field::OpenCell)
144
- if flags_around(x, y) >= self[x, y].number then
145
- (-1..1).each do |v|
146
- (-1..1).each { |h| click!(x+h, y+v) unless (v==0 && h==0) or has_flag?(x+h, y+v) }
147
- end
148
- end
149
- end
150
-
151
- private
152
-
153
- def cell_exists?(x, y)
154
- ((0...@w).include? x) && ((0...@h).include? y)
155
- end
156
-
157
- def has_flag?(x, y)
158
- return false unless cell_exists?(x, y)
159
- return self[x, y].flag
160
- end
161
-
162
- def bomb?(x, y)
163
- cell_exists?(x, y) && (self[x, y].is_a? Bomb)
164
- end
165
-
166
- def can_be_discovered?(x, y)
167
- return false unless cell_exists?(x, y)
168
- return false if self[x, y].flag
169
- cell_exists?(x, y) && (self[x, y].is_a? EmptyCell) && !bomb?(x, y) && (bombs_around(x, y) == 0)
170
- end
171
-
172
- def open(x, y)
173
- self[x, y] = OpenCell.new(bombs_around(x, y)) unless (self[x, y].is_a? OpenCell) or has_flag?(x, y)
174
- end
175
-
176
- def neighbors
177
- (-1..1).each do |col|
178
- (-1..1).each { |row| yield row, col unless col==0 && row == 0 }
179
- end
180
- end
181
-
182
- def discover(x, y)
183
- open(x, y)
184
- neighbors do |col, row|
185
- cx, cy = x+row, y+col
186
- next unless cell_exists?(cx, cy)
187
- discover(cx, cy) if can_be_discovered?(cx, cy)
188
- open(cx, cy)
189
- end
190
- end
191
-
192
- def count_neighbors
193
- return 0 unless block_given?
194
- count = 0
195
- neighbors { |h, v| count += 1 if yield(h, v) }
196
- count
197
- end
198
-
199
- def bombs_around(x, y)
200
- count_neighbors { |v, h| bomb?(x+h, y+v) }
201
- end
202
-
203
- def flags_around(x, y)
204
- count_neighbors { |v, h| has_flag?(x+h, y+v) }
205
- end
206
-
207
- def die!(x, y)
208
- self[x, y].exploded = true
209
- @game_over = true
210
- end
211
-
212
- def plant_bomb(x, y)
213
- self[x, y].is_a?(EmptyCell) ? self[x, y] = Bomb.new : false
214
- end
215
-
216
- def plant_bombs
217
- @bombs.times { redo unless plant_bomb(rand(@w), rand(@h)) }
218
- end
219
-
220
- def [](*args)
221
- x, y = args
222
- raise "Cell #{x}:#{y} does not exists!" unless cell_exists?(x, y)
223
- @field[y][x]
224
- end
225
-
226
- def []=(*args)
227
- x, y, v = args
228
- cell_exists?(x, y) ? @field[y][x] = v : false
229
- end
230
- end
231
-
232
- Shoes.app width: 730, height: 450, title: 'Minesweeper' do
233
- def render_field
234
- clear do
235
- background rgb(50, 50, 90, 0.7)
236
- flow margin: 4 do
237
- flow do
238
- button("Beginner") { new_game :beginner }
239
- button("Intermediate") { new_game :intermediate }
240
- button("Expert") { new_game :expert }
241
- end
242
- end
243
- stack do @status = para stroke: white end
244
- @field.paint
245
- para "Left click - open cell, right click - put flag, middle click - reveal empty cells", top: 420, left: 0, stroke: white, size: 11
246
- end
247
- end
248
-
249
- def new_game level
250
- @field = Field.new self, level
251
- #translate -@old_offset.first, -@old_offset.last unless @old_offset.nil?
252
- #translate @field.offset.first, @field.offset.last
253
- #@old_offset = @field.offset
254
- $x, $y = @field.offset.first, @field.offset.last
255
- render_field
256
- end
257
-
258
- new_game :beginner
259
- every { @status.replace "Time: #{@field.total_time.to_i} Bombs left: #{@field.bombs_left}" }
260
-
261
- click do |button, x, y|
262
- next if @field.game_over? || @field.all_found?
263
- fx, fy = ((x-@field.offset.first) / @field.cell_size).to_i, ((y-@field.offset.last) / @field.cell_size).to_i
264
- @field.click!(fx, fy) if button == 1
265
- @field.reveal!(fx, fy) if button == 2
266
- @field.flag!(fx, fy) if button == 3
267
-
268
- render_field
269
- alert("Winner!\nTotal time: #{@field.total_time}") if @field.all_found?
270
- alert("Bang!\nYou loose.") if @field.game_over?
271
- end
272
- end