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 +4 -4
- data/README.md +12 -10
- data/bin/2048 +11 -0
- data/lib/text2048.rb +1 -0
- data/lib/text2048/app.rb +31 -1
- data/lib/text2048/curses_view.rb +22 -5
- data/lib/text2048/curses_view/keyboard.rb +4 -0
- data/lib/text2048/curses_view/lcd.rb +26 -30
- data/lib/text2048/curses_view/tile_effects.rb +2 -0
- data/lib/text2048/high_score.rb +35 -0
- data/lib/text2048/version.rb +1 -1
- data/spec/text2048/app_spec.rb +26 -12
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9db309419e40329c97f3490cacf5b307023929e5
|
4
|
+
data.tar.gz: 24055097be1b6246422694cb75b2b72685d37253
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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/
|
7
|
-
[![Dependency Status](http://img.shields.io/gemnasium/yasuhito/text2048.svg)][gemnasium]
|
8
|
-
[![
|
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://
|
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
|
-
-
|
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)
|
data/lib/text2048.rb
CHANGED
data/lib/text2048/app.rb
CHANGED
@@ -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,
|
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)
|
data/lib/text2048/curses_view.rb
CHANGED
@@ -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
|
-
|
62
|
-
|
66
|
+
@message = 'WIN!'
|
67
|
+
draw_message
|
63
68
|
end
|
64
69
|
|
65
70
|
def game_over
|
66
|
-
|
67
|
-
|
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
|
@@ -6,32 +6,34 @@ module Text2048
|
|
6
6
|
# Renders numbers like LCDs
|
7
7
|
class LCD
|
8
8
|
BITMAPS = [
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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 =
|
30
|
-
CORNER_TOP_RIGHT =
|
31
|
-
CORNER_MIDDLE_LEFT =
|
32
|
-
CORNER_MIDDLE_RIGHT =
|
33
|
-
CORNER_BOTTOM_LEFT =
|
34
|
-
CORNER_BOTTOM_RIGHT =
|
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,
|
52
|
+
[TOP_LEFT, TOP_MIDDLE, TOP_RIGHT],
|
51
53
|
[CORNER_MIDDLE_LEFT, MIDDLE, CORNER_MIDDLE_RIGHT],
|
52
|
-
[BOTTOM_LEFT,
|
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
|
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
|
@@ -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
|
data/lib/text2048/version.rb
CHANGED
data/spec/text2048/app_spec.rb
CHANGED
@@ -17,7 +17,9 @@ describe Text2048::App do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
describe '#generate' do
|
20
|
-
Given(:view)
|
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)
|
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)
|
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',
|
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(:
|
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',
|
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(:
|
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',
|
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(:
|
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',
|
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(:
|
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.
|
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-
|
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
|