text2048 0.8.0 → 0.9.0

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