shoes 4.0.0.pre2 → 4.0.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
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