text2048 0.8.0 → 0.9.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 185c956718085eb81aef19c630b8cee21e67d71f
4
- data.tar.gz: efb909b378a7c05e887ac9f6a4a45c84dd47e9c2
3
+ metadata.gz: 9db309419e40329c97f3490cacf5b307023929e5
4
+ data.tar.gz: 24055097be1b6246422694cb75b2b72685d37253
5
5
  SHA512:
6
- metadata.gz: 253d485900f6ea785acd1de33bbdab69f46126319640062ffd80cc5779bb7efa8b3f7a7f750d65141bbeb86bfd60805865f966c4db10402cfbace5c381bdc494
7
- data.tar.gz: 91f25760bb10e3b313263ec88cc6006a38d077325296b4086eadbdd5cb909452c2161ff996ad7cf8f8c0eef9d0c0426bb43ffafb54b91a367c5723a764eca79a
6
+ metadata.gz: d8d9031ff6562432a491aab20592ad4f81148522417e1f5ef08a13686bcf13e7ba5301da9d403ad302601ca43cc874532dae8958f43a56658b3fa4fbc1587cf6
7
+ data.tar.gz: 16d316b287ac2bd945e2e428026ad40990fac2d06fadfd9c742ef5cc7088d1ee9752fe9c23e713dc3337176d3e967551d65d91996cbfde0a6d440372fc2739f1
data/README.md CHANGED
@@ -1,24 +1,25 @@
1
1
  text2048
2
2
  ========
3
- [![Gem Version](http://img.shields.io/gem/v/text2048.svg)][gem]
4
- [![Build Status](http://img.shields.io/travis/yasuhito/text2048/develop.svg)][travis]
5
- [![Code Climate](http://img.shields.io/codeclimate/github/yasuhito/text2048.svg)][codeclimate]
6
- [![Coverage Status](http://img.shields.io/coveralls/yasuhito/text2048/develop.svg)][coveralls]
7
- [![Dependency Status](http://img.shields.io/gemnasium/yasuhito/text2048.svg)][gemnasium]
8
- [![Gittip](http://img.shields.io/gittip/yasuhito.svg)][gittip]
3
+ [![Gem Version](http://img.shields.io/gem/v/text2048.svg?style=flat)][gem]
4
+ [![Build Status](http://img.shields.io/travis/yasuhito/text2048/develop.svg?style=flat)][travis]
5
+ [![Code Climate](http://img.shields.io/codeclimate/github/yasuhito/text2048.svg?style=flat)][codeclimate]
6
+ [![Coverage Status](http://img.shields.io/codeclimate/coverage/github/yasuhito/text2048.svg?style=flat)][codeclimate]
7
+ [![Dependency Status](http://img.shields.io/gemnasium/yasuhito/text2048.svg?style=flat)][gemnasium]
8
+ [![Gitter chat](http://img.shields.io/badge/GITTER-text2048-blue.svg?style=flat)][gitter]
9
+ [![Gittip](http://img.shields.io/gittip/yasuhito.svg?style=flat)][gittip]
9
10
 
10
11
  Text mode 2048 game.
11
12
 
12
13
  [gem]: https://rubygems.org/gems/text2048
13
14
  [travis]: http://travis-ci.org/yasuhito/text2048
14
15
  [codeclimate]: https://codeclimate.com/github/yasuhito/text2048
15
- [coveralls]: https://coveralls.io/r/yasuhito/text2048?branch=develop
16
16
  [gemnasium]: https://gemnasium.com/yasuhito/text2048
17
+ [gitter]: https://gitter.im/yasuhito/text2048
17
18
  [gittip]: https://www.gittip.com/yasuhito/
18
19
 
19
20
  [![Screenshot](https://raw.github.com/yasuhito/text2048/develop/screen_shot.png)][screenshot]
20
21
 
21
- [screenshot]: https://raw.github.com/yasuhito/text2048/develop/screen_shot.png
22
+ [screenshot]: https://asciinema.org/a/9577
22
23
 
23
24
  Installation
24
25
  ------------
@@ -34,8 +35,9 @@ How to Play
34
35
  $ 2048
35
36
  ```
36
37
 
37
- - Use your arrow keys to move the tiles.
38
- - +/- for increase or decrease the size of the tiles displayed.
38
+ - Use your arrow keys or vi keys ('h'/'j'/'k'/'l') to move the tiles.
39
+ - '+'/'-' to increase or decrease the size of the tiles displayed.
40
+ - 'q' to quit.
39
41
 
40
42
  Links
41
43
  -----
data/bin/2048 CHANGED
@@ -4,6 +4,17 @@
4
4
  $LOAD_PATH.unshift(File.dirname(File.realpath(__FILE__)) + '/../lib')
5
5
 
6
6
  require 'text2048/app'
7
+ require 'timeout'
8
+
9
+ app = Text2048::App.new
10
+ begin
11
+ timeout(60) { app.show_title }
12
+ rescue Timeout::Error
13
+ loop do
14
+ app.demo
15
+ break if app.wait_any_key(0.5)
16
+ end
17
+ end
7
18
 
8
19
  app = Text2048::App.new
9
20
  app.generate(2)
@@ -2,5 +2,6 @@
2
2
 
3
3
  require 'text2048/board'
4
4
  require 'text2048/curses_view'
5
+ require 'text2048/high_score'
5
6
  require 'text2048/monkey_patch/array'
6
7
  require 'text2048/text_view'
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'text2048'
4
+ require 'timeout'
4
5
 
5
6
  # This module smells of :reek:UncommunicativeModuleName
6
7
  module Text2048
@@ -9,9 +10,23 @@ module Text2048
9
10
  attr_reader :board
10
11
  attr_reader :view
11
12
 
12
- def initialize(view = CursesView.new, board = Board.new)
13
+ def initialize(view = CursesView.new,
14
+ board = Board.new,
15
+ high_score = HighScore.new)
13
16
  @view = view
14
17
  @board = board
18
+ @high_score = high_score
19
+ end
20
+
21
+ def show_title
22
+ @view.high_score(@high_score)
23
+ @view.message = 'PRESS ANY KEY TO START'
24
+ @board = Board.new([[0, 0, 0, 0],
25
+ [2, 0, 4, 8],
26
+ [0, 0, 0, 0],
27
+ [0, 0, 0, 0]])
28
+ @view.update(@board)
29
+ @view.wait_any_key
15
30
  end
16
31
 
17
32
  def generate(num_tiles = 1)
@@ -24,6 +39,20 @@ module Text2048
24
39
  @view.win if @board.win?
25
40
  @view.game_over if @board.lose?
26
41
  input @view.command
42
+ @view.high_score(@high_score)
43
+ end
44
+
45
+ def wait_any_key(seconds)
46
+ begin
47
+ timeout(seconds) { @view.wait_any_key }
48
+ rescue Timeout::Error
49
+ return false
50
+ end
51
+ true
52
+ end
53
+
54
+ def demo
55
+ input [:left, :right, :up, :down][rand(5)]
27
56
  end
28
57
 
29
58
  private
@@ -42,6 +71,7 @@ module Text2048
42
71
  def move_and_generate(command)
43
72
  last = move(command)
44
73
  generate if @board.generate?(last)
74
+ @high_score.maybe_update(@board.score)
45
75
  end
46
76
 
47
77
  def move(command)
@@ -20,20 +20,25 @@ module Text2048
20
20
  DEFAULT_WIDTH = (Tile::DEFAULT_WIDTH + 1) * 4 + 1
21
21
  DEFAULT_HEIGHT = (Tile::DEFAULT_HEIGHT + 1) * 4 + 2
22
22
 
23
+ attr_writer :message
24
+
23
25
  def initialize
24
26
  @tiles = {}
25
27
  @scale = 1
26
28
  @scale_min = 0.5
27
29
  @scale_step = 0.5
30
+ @message = nil
28
31
  @keyboard = Keyboard.new
29
32
  end
30
33
 
31
34
  def_delegator :@keyboard, :read, :command
35
+ def_delegators :@keyboard, :wait_any_key
32
36
 
33
37
  def update(board)
34
38
  maybe_init_curses
35
39
  draw_score(board.score)
36
40
  draw_tiles(board.to_a)
41
+ draw_message
37
42
  refresh
38
43
  end
39
44
 
@@ -58,13 +63,25 @@ module Text2048
58
63
  end
59
64
 
60
65
  def win
61
- setpos(rows_center, cols_center - 1)
62
- colorize(COLOR_RED) { addstr('WIN!') }
66
+ @message = 'WIN!'
67
+ draw_message
63
68
  end
64
69
 
65
70
  def game_over
66
- setpos(rows_center, cols_center - 4)
67
- colorize(COLOR_RED) { addstr('GAME OVER') }
71
+ @message = 'GAME OVER'
72
+ draw_message
73
+ end
74
+
75
+ def high_score(score)
76
+ maybe_init_curses
77
+ setpos(0, 15)
78
+ addstr("High Score: #{score.to_i}")
79
+ end
80
+
81
+ def draw_message
82
+ return unless @message
83
+ setpos(rows_center, cols_center - @message.length / 2)
84
+ colorize(COLOR_MAGENTA) { addstr(@message) }
68
85
  end
69
86
 
70
87
  private
@@ -77,7 +94,7 @@ module Text2048
77
94
  end
78
95
 
79
96
  def rows_center
80
- height / 2
97
+ height / 2 + 1
81
98
  end
82
99
 
83
100
  def cols_center
@@ -22,6 +22,10 @@ module Text2048
22
22
  KEYS[getch]
23
23
  end
24
24
 
25
+ def wait_any_key
26
+ getch
27
+ end
28
+
25
29
  private
26
30
 
27
31
  def maybe_init
@@ -6,32 +6,34 @@ module Text2048
6
6
  # Renders numbers like LCDs
7
7
  class LCD
8
8
  BITMAPS = [
9
- 0b1111111110111,
10
- 0b1010100100100,
11
- 0b1111111011101,
12
- 0b1111111101101,
13
- 0b1011110101110,
14
- 0b1111111101011,
15
- 0b1111111111011,
16
- 0b1010110100101,
17
- 0b1111111111111,
18
- 0b1111111101111
9
+ 0b111111110101011,
10
+ 0b101010010001000,
11
+ 0b111111100111001,
12
+ 0b111111110011001,
13
+ 0b101111010011010,
14
+ 0b111111110010011,
15
+ 0b111111110110011,
16
+ 0b101011010001001,
17
+ 0b111111110111011,
18
+ 0b111111110011011
19
19
  ]
20
20
 
21
21
  TOP = 0
22
22
  TOP_LEFT = 1
23
- TOP_RIGHT = 2
24
- MIDDLE = 3
25
- BOTTOM_LEFT = 4
26
- BOTTOM_RIGHT = 5
27
- BOTTOM = 6
23
+ TOP_MIDDLE = 2
24
+ TOP_RIGHT = 3
25
+ MIDDLE = 4
26
+ BOTTOM_LEFT = 5
27
+ BOTTOM_MIDDLE = 6
28
+ BOTTOM_RIGHT = 7
29
+ BOTTOM = 8
28
30
 
29
- CORNER_TOP_LEFT = 7
30
- CORNER_TOP_RIGHT = 8
31
- CORNER_MIDDLE_LEFT = 9
32
- CORNER_MIDDLE_RIGHT = 10
33
- CORNER_BOTTOM_LEFT = 11
34
- CORNER_BOTTOM_RIGHT = 12
31
+ CORNER_TOP_LEFT = 9
32
+ CORNER_TOP_RIGHT = 10
33
+ CORNER_MIDDLE_LEFT = 11
34
+ CORNER_MIDDLE_RIGHT = 12
35
+ CORNER_BOTTOM_LEFT = 13
36
+ CORNER_BOTTOM_RIGHT = 14
35
37
 
36
38
  def initialize(number)
37
39
  @number = number
@@ -47,9 +49,9 @@ module Text2048
47
49
  def digit(number)
48
50
  lines =
49
51
  [[CORNER_TOP_LEFT, TOP, CORNER_TOP_RIGHT],
50
- [TOP_LEFT, nil, TOP_RIGHT],
52
+ [TOP_LEFT, TOP_MIDDLE, TOP_RIGHT],
51
53
  [CORNER_MIDDLE_LEFT, MIDDLE, CORNER_MIDDLE_RIGHT],
52
- [BOTTOM_LEFT, nil, BOTTOM_RIGHT],
54
+ [BOTTOM_LEFT, BOTTOM_MIDDLE, BOTTOM_RIGHT],
53
55
  [CORNER_BOTTOM_LEFT, BOTTOM, CORNER_BOTTOM_RIGHT]]
54
56
  lines.map { |each| line(BITMAPS[number.to_i], each) }
55
57
  end
@@ -57,13 +59,7 @@ module Text2048
57
59
  # @todo This method smells of :reek:UtilityFunction
58
60
  # @todo This method smells of :reek:FeatureEnvy
59
61
  def line(bitmap, bits)
60
- bits.map do |each|
61
- if each
62
- (bitmap & 1 << each).zero? ? ' ' : '*'
63
- else
64
- ' '
65
- end
66
- end.join
62
+ bits.map { |each| (bitmap & 1 << each).zero? ? ' ' : '*' }.join
67
63
  end
68
64
  end
69
65
  end
@@ -15,6 +15,7 @@ module Text2048
15
15
  refresh
16
16
  sleep 0.1
17
17
  end
18
+ draw_message
18
19
  end
19
20
 
20
21
  def zoom_tiles(list)
@@ -23,6 +24,7 @@ module Text2048
23
24
  refresh
24
25
  sleep 0.05
25
26
  end
27
+ draw_message
26
28
  end
27
29
 
28
30
  private
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ # This module smells of :reek:UncommunicativeModuleName
4
+ module Text2048
5
+ # High score manager
6
+ class HighScore
7
+ DB_FILE = File.expand_path('~/.text2048')
8
+
9
+ def initialize
10
+ @score = 0
11
+ load
12
+ end
13
+
14
+ def load
15
+ @score = IO.read(DB_FILE).to_i if FileTest.exists?(DB_FILE)
16
+ @score
17
+ end
18
+
19
+ def maybe_update(score)
20
+ load
21
+ save(score) if score > @score
22
+ end
23
+
24
+ def to_i
25
+ @score
26
+ end
27
+
28
+ private
29
+
30
+ def save(score)
31
+ File.open(DB_FILE, 'w') { |file| file.print score }
32
+ @score = score
33
+ end
34
+ end
35
+ end
@@ -3,5 +3,5 @@
3
3
  # This module smells of :reek:UncommunicativeModuleName
4
4
  module Text2048
5
5
  # gem version.
6
- VERSION = '0.8.0'.freeze
6
+ VERSION = '0.9.0'.freeze
7
7
  end
@@ -17,7 +17,9 @@ describe Text2048::App do
17
17
  end
18
18
 
19
19
  describe '#generate' do
20
- Given(:view) { double('view', update: nil, zoom_tiles: nil) }
20
+ Given(:view) do
21
+ double('view', update: nil, zoom_tiles: nil, high_score: nil)
22
+ end
21
23
  Given(:app) { Text2048::App.new(view) }
22
24
 
23
25
  context 'with no arguments' do
@@ -33,18 +35,22 @@ describe Text2048::App do
33
35
 
34
36
  describe '#step' do
35
37
  Given(:new_board) do
36
- double('new_board', merged_tiles: nil, generate?: nil)
38
+ double('new_board', merged_tiles: nil, generate?: nil, score: 0)
37
39
  end
38
40
 
39
41
  context 'with command = :larger' do
40
- Given(:view) { double('view', command: :larger, larger: nil) }
42
+ Given(:view) do
43
+ double('view', command: :larger, larger: nil, high_score: nil)
44
+ end
41
45
  Given(:app) { Text2048::App.new(view) }
42
46
  When { app.step }
43
47
  Then { expect(view).to have_received(:larger) }
44
48
  end
45
49
 
46
50
  context 'with command = :smaller' do
47
- Given(:view) { double('view', command: :smaller, smaller: nil) }
51
+ Given(:view) do
52
+ double('view', command: :smaller, smaller: nil, high_score: nil)
53
+ end
48
54
  Given(:app) { Text2048::App.new(view) }
49
55
  When { app.step }
50
56
  Then { expect(view).to have_received(:smaller) }
@@ -52,10 +58,12 @@ describe Text2048::App do
52
58
 
53
59
  context 'with command = :left' do
54
60
  Given(:view) do
55
- double('view', command: :left, update: nil, pop_tiles: nil)
61
+ double('view',
62
+ command: :left, update: nil, pop_tiles: nil, high_score: nil)
56
63
  end
57
64
  Given(:board) { double('board', left: new_board, win?: nil, lose?: nil) }
58
- Given(:app) { Text2048::App.new(view, board) }
65
+ Given(:high_score) { double('high_score', maybe_update: nil) }
66
+ Given(:app) { Text2048::App.new(view, board, high_score) }
59
67
  When { app.step }
60
68
  Then { expect(board).to have_received(:left) }
61
69
  And { expect(view).to have_received(:update) }
@@ -63,12 +71,14 @@ describe Text2048::App do
63
71
 
64
72
  context 'with command = :right' do
65
73
  Given(:view) do
66
- double('view', command: :right, update: nil, pop_tiles: nil)
74
+ double('view',
75
+ command: :right, update: nil, pop_tiles: nil, high_score: nil)
67
76
  end
68
77
  Given(:board) do
69
78
  double('board', right: new_board, win?: nil, lose?: nil)
70
79
  end
71
- Given(:app) { Text2048::App.new(view, board) }
80
+ Given(:high_score) { double('high_score', maybe_update: nil) }
81
+ Given(:app) { Text2048::App.new(view, board, high_score) }
72
82
  When { app.step }
73
83
  Then { expect(board).to have_received(:right) }
74
84
  And { expect(view).to have_received(:update) }
@@ -76,10 +86,12 @@ describe Text2048::App do
76
86
 
77
87
  context 'with command = :up' do
78
88
  Given(:view) do
79
- double('view', command: :up, update: nil, pop_tiles: nil)
89
+ double('view',
90
+ command: :up, update: nil, pop_tiles: nil, high_score: nil)
80
91
  end
81
92
  Given(:board) { double('board', up: new_board, win?: nil, lose?: nil) }
82
- Given(:app) { Text2048::App.new(view, board) }
93
+ Given(:high_score) { double('high_score', maybe_update: nil) }
94
+ Given(:app) { Text2048::App.new(view, board, high_score) }
83
95
  When { app.step }
84
96
  Then { expect(board).to have_received(:up) }
85
97
  And { expect(view).to have_received(:update) }
@@ -87,10 +99,12 @@ describe Text2048::App do
87
99
 
88
100
  context 'with command = :down' do
89
101
  Given(:view) do
90
- double('view', command: :down, update: nil, pop_tiles: nil)
102
+ double('view',
103
+ command: :down, update: nil, pop_tiles: nil, high_score: nil)
91
104
  end
92
105
  Given(:board) { double('board', down: new_board, win?: nil, lose?: nil) }
93
- Given(:app) { Text2048::App.new(view, board) }
106
+ Given(:high_score) { double('high_score', maybe_update: nil) }
107
+ Given(:app) { Text2048::App.new(view, board, high_score) }
94
108
  When { app.step }
95
109
  Then { expect(board).to have_received(:down) }
96
110
  And { expect(view).to have_received(:update) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: text2048
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yasuhito Takamiya
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-15 00:00:00.000000000 Z
11
+ date: 2014-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -56,6 +56,7 @@ files:
56
56
  - lib/text2048/curses_view/lcd.rb
57
57
  - lib/text2048/curses_view/tile.rb
58
58
  - lib/text2048/curses_view/tile_effects.rb
59
+ - lib/text2048/high_score.rb
59
60
  - lib/text2048/monkey_patch/array.rb
60
61
  - lib/text2048/monkey_patch/array/board.rb
61
62
  - lib/text2048/monkey_patch/array/tile.rb