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,267 +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*cell_size, y*cell_size, cell_size-1, cell_size-1
73
- @app.stroke "#BBB" if stroke
74
- @app.line x*cell_size+1, y*cell_size+1, x*cell_size+cell_size-1, y*cell_size
75
- @app.line x*cell_size+1, y*cell_size+1, x*cell_size, y*cell_size+cell_size-1
76
- end
77
-
78
- def render_flag(x, y)
79
- @app.stroke "#000"
80
- @app.line(x*cell_size+cell_size / 4 + 1, y*cell_size + cell_size / 5, x*cell_size+cell_size / 4 + 1, y*cell_size+cell_size / 5 * 4)
81
- @app.fill "#A00"
82
- @app.rect(x*cell_size+cell_size / 4+2, 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*cell_size+3, y*cell_size+3, 13)
95
- @app.fill "#333"
96
- @app.oval(x*cell_size+5, y*cell_size+5, 7)
97
- @app.fill "#AAA"
98
- @app.oval(x*cell_size+6, 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*cell_size + cell_size / 2 + 2, y*cell_size + cell_size / 4 - 2, 2)
103
- @app.oval(x*cell_size + cell_size / 2 + 4, 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.para self[x, y].number.to_s, left: x*cell_size + 3, top: y*cell_size - 2,
113
- font: '13px', stroke: COLORS[self[x, y].number - 1]
114
- end
115
- end
116
-
117
- def paint
118
- 0.upto @h-1 do |y|
119
- 0.upto @w-1 do |x|
120
- @app.nostroke
121
- case self[x, y]
122
- when EmptyCell then render_cell(x, y)
123
- when Bomb then render_bomb(x, y)
124
- when OpenCell then render_number(x, y)
125
- end
126
- render_flag(x, y) if has_flag?(x, y) && !(game_over? && bomb?(x, y))
127
- end
128
- end
129
- end
130
-
131
- def bombs_left
132
- @bombs - @field.flatten.compact.reject {|e| !e.flag }.size
133
- end
134
-
135
- def all_found?
136
- @field.flatten.compact.reject {|e| !e.is_a?(OpenCell) }.size + @bombs == @w*@h
137
- end
138
-
139
- def reveal!(x, y)
140
- return unless cell_exists?(x, y)
141
- return unless self[x, y].is_a?(Field::OpenCell)
142
- if flags_around(x, y) >= self[x, y].number then
143
- (-1..1).each do |v|
144
- (-1..1).each { |h| click!(x+h, y+v) unless (v==0 && h==0) or has_flag?(x+h, y+v) }
145
- end
146
- end
147
- end
148
-
149
- private
150
-
151
- def cell_exists?(x, y)
152
- ((0...@w).include? x) && ((0...@h).include? y)
153
- end
154
-
155
- def has_flag?(x, y)
156
- return false unless cell_exists?(x, y)
157
- return self[x, y].flag
158
- end
159
-
160
- def bomb?(x, y)
161
- cell_exists?(x, y) && (self[x, y].is_a? Bomb)
162
- end
163
-
164
- def can_be_discovered?(x, y)
165
- return false unless cell_exists?(x, y)
166
- return false if self[x, y].flag
167
- cell_exists?(x, y) && (self[x, y].is_a? EmptyCell) && !bomb?(x, y) && (bombs_around(x, y) == 0)
168
- end
169
-
170
- def open(x, y)
171
- self[x, y] = OpenCell.new(bombs_around(x, y)) unless (self[x, y].is_a? OpenCell) or has_flag?(x, y)
172
- end
173
-
174
- def neighbors
175
- (-1..1).each do |col|
176
- (-1..1).each { |row| yield row, col unless col==0 && row == 0 }
177
- end
178
- end
179
-
180
- def discover(x, y)
181
- open(x, y)
182
- neighbors do |col, row|
183
- cx, cy = x+row, y+col
184
- next unless cell_exists?(cx, cy)
185
- discover(cx, cy) if can_be_discovered?(cx, cy)
186
- open(cx, cy)
187
- end
188
- end
189
-
190
- def count_neighbors
191
- return 0 unless block_given?
192
- count = 0
193
- neighbors { |h, v| count += 1 if yield(h, v) }
194
- count
195
- end
196
-
197
- def bombs_around(x, y)
198
- count_neighbors { |v, h| bomb?(x+h, y+v) }
199
- end
200
-
201
- def flags_around(x, y)
202
- count_neighbors { |v, h| has_flag?(x+h, y+v) }
203
- end
204
-
205
- def die!(x, y)
206
- self[x, y].exploded = true
207
- @game_over = true
208
- end
209
-
210
- def plant_bomb(x, y)
211
- self[x, y].is_a?(EmptyCell) ? self[x, y] = Bomb.new : false
212
- end
213
-
214
- def plant_bombs
215
- @bombs.times { redo unless plant_bomb(rand(@w), rand(@h)) }
216
- end
217
-
218
- def [](*args)
219
- x, y = args
220
- raise "Cell #{x}:#{y} does not exists!" unless cell_exists?(x, y)
221
- @field[y][x]
222
- end
223
-
224
- def []=(*args)
225
- x, y, v = args
226
- cell_exists?(x, y) ? @field[y][x] = v : false
227
- end
228
- end
229
-
230
- Shoes.app width: 730, height: 450, title: 'Minesweeper' do
231
- def render_field
232
- clear do
233
- background rgb(50, 50, 90, 0.7)
234
- flow margin: 4 do
235
- button("Beginner") { new_game :beginner }
236
- button("Intermediate") { new_game :intermediate }
237
- button("Expert") { new_game :expert }
238
- end
239
- stack do @status = para stroke: white end
240
- @field.paint
241
- para "Left click - open cell, right click - put flag, middle click - reveal empty cells", top: 420, left: 0, stroke: white, font: "11px"
242
- end
243
- end
244
-
245
- def new_game level
246
- @field = Field.new self, level
247
- translate -@old_offset.first, -@old_offset.last unless @old_offset.nil?
248
- translate @field.offset.first, @field.offset.last
249
- @old_offset = @field.offset
250
- render_field
251
- end
252
-
253
- new_game :beginner
254
- animate(5) { @status.replace "Time: #{@field.total_time.to_i} Bombs left: #{@field.bombs_left}" }
255
-
256
- click do |button, x, y|
257
- next if @field.game_over? || @field.all_found?
258
- fx, fy = ((x-@field.offset.first) / @field.cell_size).to_i, ((y-@field.offset.last) / @field.cell_size).to_i
259
- @field.click!(fx, fy) if button == 1
260
- @field.reveal!(fx, fy) if button == 2
261
- @field.flag!(fx, fy) if button == 3
262
-
263
- render_field
264
- alert("Winner!\nTotal time: #{@field.total_time}") if @field.all_found?
265
- alert("Bang!\nYou loose.") if @field.game_over?
266
- end
267
- end
@@ -1,325 +0,0 @@
1
- # The original is Red Shoes built-in sample: expert-othello.rb
2
- # A little bit edited for Green Shoes.
3
-
4
- # Othello
5
- # by tieg
6
- # 1/13/08
7
- # with help: DeeJay, Ryan M. from mailing list
8
- #
9
- # FIXME bug if it memorizes it but it's not a valid move
10
- #
11
- module Othello
12
-
13
- PIECE_WIDTH = 62
14
- PIECE_HEIGHT = 62
15
- TOP_OFFSET = 47
16
- LEFT_OFFSET = 12
17
- SPACE = ' ' * 57
18
-
19
- class Game
20
- BOARD_SIZE = [8,8]
21
-
22
- attr_accessor :p1, :p2, :board, :board_history
23
-
24
- def initialize
25
- @board_history = []
26
- @p1 = Player.new(:black, pieces_per_player)
27
- @p2 = Player.new(:white, pieces_per_player)
28
- @board = new_board
29
- lay_initial_pieces
30
- end
31
-
32
- def next_turn(check_available_moves=true)
33
- @current_player = next_player
34
- if check_available_moves && skip_turn?
35
- # FIXME Possible infinite loop if neither player has a good move?
36
- next_turn
37
- raise "Player #{@current_player.piece} (#{@current_player.color}) has no available moves. Player #{next_player.piece}'s (#{next_player.color}) turn."
38
- end
39
- end
40
-
41
- def current_player
42
- @current_player ||= @p1
43
- end
44
-
45
- def next_player
46
- current_player == @p1 ? @p2 : @p1
47
- end
48
-
49
- # Build the array for the board, with zero-based arrays.
50
- def new_board
51
- Array.new(BOARD_SIZE[0]) do # build each cols L to R
52
- Array.new(BOARD_SIZE[1]) do # insert cells in each col
53
- 0
54
- end
55
- end
56
- end
57
-
58
- # Lay the initial 4 pieces in the middle
59
- def lay_initial_pieces
60
- lay_piece([4, 3], false)
61
- next_turn(false)
62
- lay_piece([3, 3], false)
63
- next_turn(false)
64
- lay_piece([3, 4], false)
65
- next_turn(false)
66
- lay_piece([4, 4], false)
67
- next_turn(false)
68
- end
69
-
70
- def lay_piece(c=[0,0], check_adjacent_pieces=true)
71
- memorize_board
72
- piece = current_player.piece
73
- opp_piece = current_player.opp_piece
74
- raise "Spot already taken." if board_at(c) != 0
75
- if check_adjacent_pieces
76
- pieces_to_change = []
77
- pieces_to_change << check_direction(c, [ 0, 1], piece, opp_piece) # N
78
- pieces_to_change << check_direction(c, [ 1, 1], piece, opp_piece) # NE
79
- pieces_to_change << check_direction(c, [ 1, 0], piece, opp_piece) # E
80
- pieces_to_change << check_direction(c, [ 1,-1], piece, opp_piece) # SE
81
- pieces_to_change << check_direction(c, [ 0,-1], piece, opp_piece) # S
82
- pieces_to_change << check_direction(c, [-1,-1], piece, opp_piece) # SW
83
- pieces_to_change << check_direction(c, [-1, 0], piece, opp_piece) # W
84
- pieces_to_change << check_direction(c, [-1, 1], piece, opp_piece) # NW
85
- raise "You must move to a spot that will turn your opponent's piece." if pieces_to_change.compact.all? { |a| a.empty? }
86
- pieces_to_change.compact.each { |direction| direction.each { |i| @board[i[0]][i[1]] = piece } }
87
- end
88
- current_player.pieces -= 1
89
- @board[c[0]][c[1]] = piece
90
- current_winner = calculate_current_winner
91
- raise "Game over. Player #{current_winner.piece} wins with #{current_winner.pieces_on_board} pieces!" if @p1.pieces + @p2.pieces == 0
92
- end
93
-
94
- def skip_turn?
95
- possibles = []
96
- @board.each_with_index { |col,col_index|
97
- col.each_with_index { |cell,row_index|
98
- return false if possible_move?([col_index,row_index])
99
- }
100
- }
101
- true
102
- end
103
-
104
- def possible_move?(c=[0,0])
105
- return nil if board_at(c) != 0
106
- possible_moves = []
107
- piece = current_player.piece
108
- opp_piece = current_player.opp_piece
109
- pieces_to_change = []
110
- pieces_to_change << check_direction(c, [ 0, 1], piece, opp_piece) # N
111
- pieces_to_change << check_direction(c, [ 1, 1], piece, opp_piece) # NE
112
- pieces_to_change << check_direction(c, [ 1, 0], piece, opp_piece) # E
113
- pieces_to_change << check_direction(c, [ 1,-1], piece, opp_piece) # SE
114
- pieces_to_change << check_direction(c, [ 0,-1], piece, opp_piece) # S
115
- pieces_to_change << check_direction(c, [-1,-1], piece, opp_piece) # SW
116
- pieces_to_change << check_direction(c, [-1, 0], piece, opp_piece) # W
117
- pieces_to_change << check_direction(c, [-1, 1], piece, opp_piece) # NW
118
- return nil if pieces_to_change.compact.all? { |a| a.empty? }
119
- true
120
- end
121
-
122
- def memorize_board
123
- dup_board = new_board
124
- dup_board = []
125
- @board.each do |col|
126
- dup_board << col.dup
127
- end
128
- @board_history << { player: current_player, board: dup_board }
129
- end
130
-
131
- def undo!
132
- last_move = @board_history.pop
133
- @board = last_move[:board]
134
- @current_player = last_move[:player]
135
- @current_player.pieces += 1
136
- end
137
-
138
- def calculate_current_winner
139
- @p1.pieces_on_board, @p2.pieces_on_board = 0, 0
140
- @board.each { |row|
141
- row.each { |cell|
142
- if cell == 1
143
- @p1.pieces_on_board += 1
144
- else
145
- @p2.pieces_on_board += 1
146
- end
147
- }
148
- }
149
- @p1.pieces_on_board > @p2.pieces_on_board ? @p1 : @p2
150
- end
151
-
152
- def check_direction(c, dir, piece, opp_piece)
153
- c_adjacent = next_in_direction(c.dup, dir)
154
- c_last = nil
155
- pieces_in_between = []
156
- # Find the last piece if there is one.
157
- while(valid_location?(c_adjacent))
158
- if board_at(c_adjacent) == opp_piece
159
- pieces_in_between << c_adjacent.dup
160
- elsif board_at(c_adjacent) == piece && pieces_in_between.size > 0
161
- c_last = c_adjacent
162
- break
163
- else
164
- break
165
- end
166
- c_adjacent = next_in_direction(c_adjacent, dir)
167
- end
168
-
169
- pieces_in_between.empty? || c_last.nil? ? nil : pieces_in_between
170
- end
171
-
172
- # Find the value of the board at the given coordinate.
173
- def board_at(c)
174
- @board[c[0]][c[1]]
175
- end
176
-
177
- # Is this a valid location on board?
178
- def valid_location?(c=[1,1])
179
- c[0] >= 0 && c[1] >= 0 && c[0] < BOARD_SIZE[0] && c[1] < BOARD_SIZE[1]
180
- end
181
-
182
- # Perform the operations to get the next spot in the appropriate direction
183
- def next_in_direction(c, dir)
184
- c[0] += dir[0]
185
- c[1] += dir[1]
186
- c
187
- end
188
-
189
- private
190
- def pieces_per_player
191
- total_squares / 2
192
- end
193
-
194
- # The total number of squares
195
- def total_squares
196
- BOARD_SIZE[0] * BOARD_SIZE[1]
197
- end
198
-
199
- class Player
200
- attr_accessor :pieces, :color, :pieces_on_board
201
-
202
- def initialize(color=:black,pieces=0)
203
- @pieces = pieces
204
- @pieces_on_board = 0 # used only in calculating winner
205
- @color = color
206
- end
207
-
208
- def piece
209
- color == :black ? 1 : 2
210
- end
211
-
212
- def opp_piece
213
- color == :black ? 2 : 1
214
- end
215
- end
216
- end
217
-
218
- def draw_player_1(first_turn=false)
219
- stack width: width-5, height: 50 do
220
- if GAME.current_player==GAME.p1
221
- background yellow
222
- border black, strokewidth: 10
223
- para strong("Player 1 (#{GAME.current_player.color}) turn"), margin: [20, 15, 0, 0]
224
- else
225
- background white
226
- border black, strokewidth: 10
227
- undo = GAME.board_history.empty? ? nil : link("Undo last move"){ GAME.undo!; draw_board }
228
- para strong("Player 1"), SPACE, undo, margin: [20, 15, 0, 0]
229
- end
230
- end
231
- end
232
-
233
- def draw_player_2(first_turn=false)
234
- stack width: width-5, height: 50 do
235
- if GAME.current_player==GAME.p2
236
- background yellow
237
- border black, strokewidth: 10
238
- para strong("Player 2 (#{GAME.current_player.color}) turn"), margin: [20, 15, 0, 0]
239
- else
240
- background white
241
- border black, strokewidth: 10
242
- undo = GAME.board_history.empty? ? nil : link("Undo last move"){ GAME.undo!; draw_board }
243
- para strong("Player 2"), SPACE, undo, margin: [20, 15, 0, 0]
244
- end
245
- end
246
- end
247
-
248
-
249
- def draw_board
250
- clear do
251
- background black
252
- draw_player_1
253
-
254
- stack width: width, height: 500 do
255
- fill rgb(0, 190, 0)
256
- #rect left: 0, top: 0, width: 495, height: 495
257
-
258
- GAME.board.each_with_index do |col, col_index|
259
- col.each_with_index do |cell, row_index|
260
- left, top = left_top_corner_of_piece(col_index, row_index)
261
- left = left - LEFT_OFFSET + 10
262
- top = top - TOP_OFFSET + 50
263
- fill rgb(0, 255, 0)
264
- strokewidth 1
265
- stroke rgb(0, 100, 0)
266
- rect left: left, top: top, width: PIECE_WIDTH, height: PIECE_HEIGHT
267
-
268
- if cell != 0
269
- strokewidth 0
270
- fill (cell == 1 ? rgb(100,100,100) : rgb(155,155,155))
271
- oval(left+3, top+4, PIECE_WIDTH-10, PIECE_HEIGHT-10)
272
-
273
- fill (cell == 1 ? black : white)
274
- oval(left+5, top+5, PIECE_WIDTH-10, PIECE_HEIGHT-10)
275
- end
276
- end
277
- end
278
- end
279
-
280
- draw_player_2
281
- end
282
- end
283
-
284
- def left_top_corner_of_piece(a,b)
285
- [(a*PIECE_WIDTH+LEFT_OFFSET), (b*PIECE_HEIGHT+TOP_OFFSET)]
286
- end
287
-
288
- def right_bottom_corner_of_piece(a,b)
289
- left_top_corner_of_piece(a,b).map { |coord| coord + PIECE_WIDTH }
290
- end
291
-
292
- def find_piece(x,y)
293
- GAME.board.each_with_index { |row_array, row|
294
- row_array.each_with_index { |col_array, col|
295
- left, top = left_top_corner_of_piece(col, row).map { |i| i - 5}
296
- right, bottom = right_bottom_corner_of_piece(col, row).map { |i| i -5 }
297
- return [col, row] if x >= left && x <= right && y >= top && y <= bottom
298
- }
299
- }
300
- return false
301
- end
302
- end
303
-
304
-
305
- Shoes.app width: 520, height: 600 do
306
- extend Othello
307
- GAME = Othello::Game.new
308
-
309
- draw_board
310
-
311
- click { |button, x, y|
312
- if coords = find_piece(x,y)
313
- begin
314
- GAME.lay_piece(coords)
315
- GAME.next_turn
316
- draw_board
317
- rescue => e
318
- #draw_board
319
- alert(e.message)
320
- end
321
- else
322
- # alert("Not a piece.")
323
- end
324
- }
325
- end