threesmodel 0.0.3
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 +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +22 -0
- data/README.md +51 -0
- data/Rakefile +28 -0
- data/features/basic_folding.feature +66 -0
- data/features/basic_summing.feature +82 -0
- data/features/game_over.feature +18 -0
- data/features/scoring.feature +112 -0
- data/features/start_game.feature +14 -0
- data/features/steps/basic_steps.rb +41 -0
- data/features/steps/game_over_steps.rb +44 -0
- data/features/steps/game_play_steps.rb +39 -0
- data/lib/candidate_extractor.rb +47 -0
- data/lib/candidate_translator.rb +26 -0
- data/lib/game_board_folder.rb +86 -0
- data/lib/game_creator.rb +30 -0
- data/lib/game_over_checker.rb +18 -0
- data/lib/line_folder.rb +93 -0
- data/lib/next_number_determinator.rb +21 -0
- data/lib/next_number_positioner.rb +10 -0
- data/lib/score_calculator.rb +27 -0
- data/lib/threesmodel/version.rb +3 -0
- data/lib/threesmodel.rb +113 -0
- data/spec/candidate_extraction_spec.rb +34 -0
- data/spec/candidate_translator_spec.rb +36 -0
- data/spec/custom_matchers.rb +27 -0
- data/spec/game_board_folder_spec.rb +50 -0
- data/spec/game_creator_spec.rb +36 -0
- data/spec/line_folder_spec.rb +87 -0
- data/spec/next_number_determination_spec.rb +38 -0
- data/spec/next_number_positioner_spec.rb +28 -0
- data/spec/spec_helper.rb +17 -0
- data/threesmodel.gemspec +23 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 957115b434fa33462e405bee92fa5d888674a0ca
|
4
|
+
data.tar.gz: 5b7a6860503769c440c8218678f4324bb793a033
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fe6510bb2b3bb1336fdb24e9d1e7e36e1cc71e522ffc6aec469ecf9d276c12f41a825e428346a3c92d2ab68ae2ba940b391b8330eef7dcf176707360bf09d9bd
|
7
|
+
data.tar.gz: 231be835a76ee3e4ba4e8c091f556ade7611abeccab1db1216970bcf1920d797e084d5d24643b756bdd28ea859f20f5080082752a8893e08f9d5836a4d541f3a
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Måns Sandström
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# Threesmodel
|
2
|
+
|
3
|
+
This is an attempt at emulating the game model of the excellent game "Threes".
|
4
|
+
It is implemented in Ruby and specified with Gehrkin and rspec examples.
|
5
|
+
The gem is not indended to be a game in it self, but with relative ease one
|
6
|
+
could use it as the game engine for a command line or a web version of the game.
|
7
|
+
It supports playing multiple games simultaneously.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'threesmodel'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install threesmodel
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
Creating and playing a basic game works like this:
|
26
|
+
|
27
|
+
require 'threesmodel'
|
28
|
+
game_controller = Threesmodel::GameController.new
|
29
|
+
game_state = game_controller.start_new_game
|
30
|
+
|
31
|
+
The game state object is a hash with the keys :id (the identifier of the game),
|
32
|
+
:game the layout of the current game board (as an instance of a Matrix class),
|
33
|
+
:game_over (boolean that denotes whether the game is over or not),
|
34
|
+
:next_number states the number to be added after the next fold and
|
35
|
+
:score that states the current score.
|
36
|
+
|
37
|
+
Play by issuing fold calls to the game controller identifying the game with the id like this:
|
38
|
+
|
39
|
+
game_state = game_controller.fold_left(game_state[:id])
|
40
|
+
game_state = game_controller.fold_right(game_state[:id])
|
41
|
+
game_state = game_controller.fold_up(game_state[:id])
|
42
|
+
game_state = game_controller.fold_down(game_state[:id])
|
43
|
+
|
44
|
+
|
45
|
+
## Contributing
|
46
|
+
|
47
|
+
1. Fork it
|
48
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
49
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
50
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
51
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'cucumber/rake/task'
|
4
|
+
|
5
|
+
Cucumber::Rake::Task.new(:cucumber) do |t|
|
6
|
+
|
7
|
+
#t.cucumber_opts = '--format Fivemat'
|
8
|
+
end
|
9
|
+
|
10
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
11
|
+
t.rspec_opts = '--format Fivemat'
|
12
|
+
end
|
13
|
+
|
14
|
+
RSpec::Core::RakeTask.new(:htmlspec) do |t|
|
15
|
+
t.rspec_opts = '--format html --out reports/rspec_results.html'
|
16
|
+
end
|
17
|
+
|
18
|
+
task :default => :spec
|
19
|
+
|
20
|
+
task :test => [:cucumber, :spec]
|
21
|
+
|
22
|
+
namespace :rspec_report do
|
23
|
+
desc 'Run all specs, generate RSpec report and open it in the browser'
|
24
|
+
task :browser do
|
25
|
+
Rake::Task[:htmlspec].invoke
|
26
|
+
`open reports/rspec_results.html` # This only works if running OS X.
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
Feature: The start situation is playable and 1's fold into 2's to create 3's.
|
2
|
+
Scenario: I have just started a game. The board is full of small numbers and empty cells.
|
3
|
+
|
4
|
+
Given a gameboard
|
5
|
+
|0|1|2|0|
|
6
|
+
|0|1|2|0|
|
7
|
+
|0|1|2|0|
|
8
|
+
|0|1|2|0|
|
9
|
+
When the game is folded right to left
|
10
|
+
Then the gameboard looks like
|
11
|
+
|1|2|0|0|
|
12
|
+
|1|2|0|0|
|
13
|
+
|1|2|0|0|
|
14
|
+
|1|2|0|0|
|
15
|
+
|
16
|
+
Scenario: I am folding ones and twos in a fairly empty board
|
17
|
+
Given a gameboard
|
18
|
+
|1|2|0|0|
|
19
|
+
|1|2|0|0|
|
20
|
+
|1|2|0|0|
|
21
|
+
|1|2|0|0|
|
22
|
+
When the game is folded right to left
|
23
|
+
Then the gameboard looks like
|
24
|
+
|3|0|0|0|
|
25
|
+
|3|0|0|0|
|
26
|
+
|3|0|0|0|
|
27
|
+
|3|0|0|0|
|
28
|
+
|
29
|
+
Scenario: I am folding right over zeros
|
30
|
+
Given a gameboard
|
31
|
+
|1|2|0|0|
|
32
|
+
|1|2|0|0|
|
33
|
+
|1|2|0|0|
|
34
|
+
|1|2|0|0|
|
35
|
+
When the game is folded left to right
|
36
|
+
Then the gameboard looks like
|
37
|
+
|0|1|2|0|
|
38
|
+
|0|1|2|0|
|
39
|
+
|0|1|2|0|
|
40
|
+
|0|1|2|0|
|
41
|
+
|
42
|
+
Scenario: I am folding up over zeros
|
43
|
+
Given a gameboard
|
44
|
+
|0|0|0|0|
|
45
|
+
|2|2|2|2|
|
46
|
+
|1|1|1|1|
|
47
|
+
|0|0|0|0|
|
48
|
+
When the game is folded upwards
|
49
|
+
Then the gameboard looks like
|
50
|
+
|2|2|2|2|
|
51
|
+
|1|1|1|1|
|
52
|
+
|0|0|0|0|
|
53
|
+
|0|0|0|0|
|
54
|
+
|
55
|
+
Scenario: I am folding down over zeros
|
56
|
+
Given a gameboard
|
57
|
+
|0|0|0|0|
|
58
|
+
|2|2|2|2|
|
59
|
+
|1|1|1|1|
|
60
|
+
|0|0|0|0|
|
61
|
+
When the game is folded downwards
|
62
|
+
Then the gameboard looks like
|
63
|
+
|0|0|0|0|
|
64
|
+
|0|0|0|0|
|
65
|
+
|2|2|2|2|
|
66
|
+
|1|1|1|1|
|
@@ -0,0 +1,82 @@
|
|
1
|
+
Feature: The start situation is playable and equal numbers fold to create new, double numbers.
|
2
|
+
Scenario: Threes will fold into sixes.
|
3
|
+
Given a gameboard
|
4
|
+
|0| 0|0|0|
|
5
|
+
|0| 0|0|0|
|
6
|
+
|3| 6|0|0|
|
7
|
+
|3|12|2|0|
|
8
|
+
When the game is folded downwards
|
9
|
+
Then the gameboard looks like
|
10
|
+
|0| 0|0|0|
|
11
|
+
|0| 0|0|0|
|
12
|
+
|0| 6|0|0|
|
13
|
+
|6|12|2|0|
|
14
|
+
|
15
|
+
Scenario: Equal numbers in several lines
|
16
|
+
Given a gameboard
|
17
|
+
|1|2| 0| 0|
|
18
|
+
|1|2| 0| 0|
|
19
|
+
|3|6|12|24|
|
20
|
+
|3|6|12|24|
|
21
|
+
When the game is folded downwards
|
22
|
+
Then the gameboard looks like
|
23
|
+
|0| 0| 0| 0|
|
24
|
+
|1| 2| 0| 0|
|
25
|
+
|1| 2| 0| 0|
|
26
|
+
|6|12|24|48|
|
27
|
+
|
28
|
+
Scenario: Equal numbers in the middle of the line
|
29
|
+
Given a gameboard
|
30
|
+
|6|2| 3| 0|
|
31
|
+
|6|3|12|24|
|
32
|
+
|6|3|12|24|
|
33
|
+
|3|6| 3| 3|
|
34
|
+
When the game is folded downwards
|
35
|
+
Then the gameboard looks like
|
36
|
+
| 0|0| 0| 0|
|
37
|
+
| 6|2| 3| 0|
|
38
|
+
|12|6|24|48|
|
39
|
+
| 3|6| 3| 3|
|
40
|
+
|
41
|
+
Scenario: Fold an unanimous matrix completely
|
42
|
+
Given a gameboard
|
43
|
+
|12|12|12|12|
|
44
|
+
|12|12|12|12|
|
45
|
+
|12|12|12|12|
|
46
|
+
|12|12|12|12|
|
47
|
+
When the game is folded downwards
|
48
|
+
Then the gameboard looks like
|
49
|
+
| 0| 0| 0| 0|
|
50
|
+
|12|12|12|12|
|
51
|
+
|12|12|12|12|
|
52
|
+
|24|24|24|24|
|
53
|
+
When the game is folded downwards
|
54
|
+
Then the gameboard looks like
|
55
|
+
| 0| 0| 0| 0|
|
56
|
+
| 0| 0| 0| 0|
|
57
|
+
|24|24|24|24|
|
58
|
+
|24|24|24|24|
|
59
|
+
When the game is folded downwards
|
60
|
+
Then the gameboard looks like
|
61
|
+
| 0| 0| 0| 0|
|
62
|
+
| 0| 0| 0| 0|
|
63
|
+
| 0| 0| 0| 0|
|
64
|
+
|48|48|48|48|
|
65
|
+
When the game is folded right
|
66
|
+
Then the gameboard looks like
|
67
|
+
|0| 0| 0| 0|
|
68
|
+
|0| 0| 0| 0|
|
69
|
+
|0| 0| 0| 0|
|
70
|
+
|0|48|48|96|
|
71
|
+
When the game is folded right
|
72
|
+
Then the gameboard looks like
|
73
|
+
|0|0| 0| 0|
|
74
|
+
|0|0| 0| 0|
|
75
|
+
|0|0| 0| 0|
|
76
|
+
|0|0|96|96|
|
77
|
+
When the game is folded right
|
78
|
+
Then the gameboard looks like
|
79
|
+
|0|0|0| 0|
|
80
|
+
|0|0|0| 0|
|
81
|
+
|0|0|0| 0|
|
82
|
+
|0|0|0|192|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Feature: A game ends when there is no foldable line.
|
2
|
+
Scenario: An unfoldable game board means that the game is over.
|
3
|
+
Given an unfoldable game board
|
4
|
+
Then the game is over
|
5
|
+
|
6
|
+
Scenario: A foldable game board means that the game continues.
|
7
|
+
Given a foldable game board
|
8
|
+
Then the game continues
|
9
|
+
|
10
|
+
Scenario: A game board that folds in only one direction means that the game continues.
|
11
|
+
Given a game board that only folds left and up
|
12
|
+
Then the game continues
|
13
|
+
Given a game board that only folds left and down
|
14
|
+
Then the game continues
|
15
|
+
Given a game board that only folds right and up
|
16
|
+
Then the game continues
|
17
|
+
Given a game board that only folds right and down
|
18
|
+
Then the game continues
|
@@ -0,0 +1,112 @@
|
|
1
|
+
Feature: For every game state there is a score.
|
2
|
+
Scenario: Ones and twos give zero points.
|
3
|
+
Given a gameboard
|
4
|
+
|0|0|0|1|
|
5
|
+
|0|1|2|0|
|
6
|
+
|2|1|0|2|
|
7
|
+
|1|2|1|0|
|
8
|
+
Then score is:"0"
|
9
|
+
|
10
|
+
Scenario: A three gives 3 points
|
11
|
+
Given a gameboard
|
12
|
+
|0|0|0|1|
|
13
|
+
|0|1|2|0|
|
14
|
+
|2|1|0|2|
|
15
|
+
|1|2|1|3|
|
16
|
+
Then score is:"3"
|
17
|
+
|
18
|
+
Scenario: A six gives 9 points
|
19
|
+
Given a gameboard
|
20
|
+
|0|0|0|1|
|
21
|
+
|0|1|2|0|
|
22
|
+
|2|1|0|2|
|
23
|
+
|1|2|1|6|
|
24
|
+
Then score is:"9"
|
25
|
+
|
26
|
+
Scenario: A 12 gives 27 points
|
27
|
+
Given a gameboard
|
28
|
+
|0|0|0| 1|
|
29
|
+
|0|1|2| 0|
|
30
|
+
|2|1|0| 2|
|
31
|
+
|1|2|1|12|
|
32
|
+
Then score is:"27"
|
33
|
+
|
34
|
+
Scenario: A 24 gives 81 points
|
35
|
+
Given a gameboard
|
36
|
+
|0|0|0| 1|
|
37
|
+
|0|1|2| 0|
|
38
|
+
|2|1|0| 2|
|
39
|
+
|1|2|1|24|
|
40
|
+
Then score is:"81"
|
41
|
+
|
42
|
+
Scenario: A 48 gives 243 points
|
43
|
+
Given a gameboard
|
44
|
+
|0|0|0| 1|
|
45
|
+
|0|1|2| 0|
|
46
|
+
|2|1|0| 2|
|
47
|
+
|1|2|1|48|
|
48
|
+
Then score is:"243"
|
49
|
+
|
50
|
+
Scenario: A 96 gives 729 points
|
51
|
+
Given a gameboard
|
52
|
+
|0|0|0| 1|
|
53
|
+
|0|1|2| 0|
|
54
|
+
|2|1|0| 2|
|
55
|
+
|1|2|1|96|
|
56
|
+
Then score is:"729"
|
57
|
+
|
58
|
+
Scenario: A 192 gives 2187 points
|
59
|
+
Given a gameboard
|
60
|
+
|0|0|0| 1|
|
61
|
+
|0|1|2| 0|
|
62
|
+
|2|1|0| 2|
|
63
|
+
|1|2|1|192|
|
64
|
+
Then score is:"2187"
|
65
|
+
|
66
|
+
Scenario: A 384 gives 6561 points
|
67
|
+
Given a gameboard
|
68
|
+
|0|0|0| 1|
|
69
|
+
|0|1|2| 0|
|
70
|
+
|2|1|0| 2|
|
71
|
+
|1|2|1|384|
|
72
|
+
Then score is:"6561"
|
73
|
+
|
74
|
+
Scenario: A 768 gives 19683 points
|
75
|
+
Given a gameboard
|
76
|
+
|0|0|0| 1|
|
77
|
+
|0|1|2| 0|
|
78
|
+
|2|1|0| 2|
|
79
|
+
|1|2|1|768|
|
80
|
+
Then score is:"19683"
|
81
|
+
|
82
|
+
Scenario: A 1536 gives 59049 points
|
83
|
+
Given a gameboard
|
84
|
+
|0|0|0| 1|
|
85
|
+
|0|1|2| 0|
|
86
|
+
|2|1|0| 2|
|
87
|
+
|1|2|1|1536|
|
88
|
+
Then score is:"59049"
|
89
|
+
|
90
|
+
Scenario: A 3072 gives 177147 points
|
91
|
+
Given a gameboard
|
92
|
+
|0|0|0| 1|
|
93
|
+
|0|1|2| 0|
|
94
|
+
|2|1|0| 2|
|
95
|
+
|1|2|1|3072|
|
96
|
+
Then score is:"177147"
|
97
|
+
|
98
|
+
Scenario: A 6144 gives 531441 points
|
99
|
+
Given a gameboard
|
100
|
+
|0|0|0| 1|
|
101
|
+
|0|1|2| 0|
|
102
|
+
|2|1|0| 2|
|
103
|
+
|1|2|1|6144|
|
104
|
+
Then score is:"531441"
|
105
|
+
|
106
|
+
Scenario: All points are summed up
|
107
|
+
Given a gameboard
|
108
|
+
| 1| 2| 3| 6|
|
109
|
+
| 12| 24| 48| 96|
|
110
|
+
| 192| 384|768|1536|
|
111
|
+
|3072|6144| 0| 0|
|
112
|
+
Then score is:"797160"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Feature: Start a new game.
|
2
|
+
Scenario: A newly created game is not over before first fold.
|
3
|
+
Given a new game is started
|
4
|
+
Then the game is not over
|
5
|
+
|
6
|
+
Scenario: A newly created game is identified by an id.
|
7
|
+
Given a new game is started
|
8
|
+
Then an id is attached to the game
|
9
|
+
|
10
|
+
Scenario: A newly created game returns a game board with nine cells filled.
|
11
|
+
Given a new game is started
|
12
|
+
Then the game board has 9 cells filled
|
13
|
+
And the board contains no other but the following numbers:
|
14
|
+
|0|1|2|3|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'Matrix'
|
2
|
+
require_relative '../../lib/game_board_folder'
|
3
|
+
require_relative '../../lib/score_calculator'
|
4
|
+
|
5
|
+
Given(/^a gameboard$/) do |table|
|
6
|
+
@game_board = GameBoardFolder.new
|
7
|
+
matrix = table.raw
|
8
|
+
matrix = matrix.map{|l| l.map{|cell| cell.strip.to_i}}
|
9
|
+
@state = Matrix.rows(matrix)
|
10
|
+
end
|
11
|
+
|
12
|
+
When(/^the game is folded right to left$/) do
|
13
|
+
@state = @game_board.fold_left @state
|
14
|
+
end
|
15
|
+
|
16
|
+
When(/^the game is folded left to right$/) do
|
17
|
+
@state = @game_board.fold_right @state
|
18
|
+
end
|
19
|
+
|
20
|
+
When(/^the game is folded upwards$/) do
|
21
|
+
@state = @game_board.fold_up @state
|
22
|
+
end
|
23
|
+
|
24
|
+
When(/^the game is folded downwards$/) do
|
25
|
+
@state = @game_board.fold_down @state
|
26
|
+
end
|
27
|
+
|
28
|
+
When(/^the game is folded right$/) do
|
29
|
+
@state = @game_board.fold_right @state
|
30
|
+
end
|
31
|
+
|
32
|
+
Then(/^the gameboard looks like$/) do |table|
|
33
|
+
matrix = table.raw
|
34
|
+
matrix = matrix.map{|l| l.map{|cell| cell.strip.to_i}}
|
35
|
+
expect(@state).to eq(Matrix.rows(matrix))
|
36
|
+
end
|
37
|
+
|
38
|
+
Then(/^score is:"(.*?)"$/) do |score|
|
39
|
+
actual_score = ScoreCalculator.score_for(@state)
|
40
|
+
expect(actual_score).to eq(score.to_i)
|
41
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'Matrix'
|
2
|
+
require_relative '../../lib/game_over_checker'
|
3
|
+
|
4
|
+
Before do
|
5
|
+
@game_over_checker = GameOverChecker.new
|
6
|
+
end
|
7
|
+
|
8
|
+
Given(/^an unfoldable game board$/) do
|
9
|
+
matrix = [[3,6,3,6],[6,3,6,3],[3,6,3,6],[6,3,6,3]]
|
10
|
+
@state = Matrix.rows(matrix)
|
11
|
+
end
|
12
|
+
|
13
|
+
Given(/^a game board that only folds left and up$/) do
|
14
|
+
matrix = [[0,6,3,6],[6,3,6,3],[3,6,3,6],[6,3,6,3]]
|
15
|
+
@state = Matrix.rows(matrix)
|
16
|
+
end
|
17
|
+
|
18
|
+
Given(/^a game board that only folds left and down$/) do
|
19
|
+
matrix = [[3,6,3,6],[6,3,6,3],[3,6,3,6],[0,3,6,3]]
|
20
|
+
@state = Matrix.rows(matrix)
|
21
|
+
end
|
22
|
+
|
23
|
+
Given(/^a game board that only folds right and up$/) do
|
24
|
+
matrix = [[3,6,3,0],[6,3,6,3],[3,6,3,6],[6,3,6,3]]
|
25
|
+
@state = Matrix.rows(matrix)
|
26
|
+
end
|
27
|
+
|
28
|
+
Given(/^a game board that only folds right and down$/) do
|
29
|
+
matrix = [[3,6,3,6],[6,3,6,3],[3,6,3,6],[6,3,6,0]]
|
30
|
+
@state = Matrix.rows(matrix)
|
31
|
+
end
|
32
|
+
|
33
|
+
Then(/^the game is over$/) do
|
34
|
+
expect(@game_over_checker.game_over?(@state)).to eq(true)
|
35
|
+
end
|
36
|
+
|
37
|
+
Given(/^a foldable game board$/) do
|
38
|
+
matrix = [[3,3,3,3],[3,3,3,3],[3,3,3,3],[3,3,3,3]]
|
39
|
+
@state = Matrix.rows(matrix)
|
40
|
+
end
|
41
|
+
|
42
|
+
Then(/^the game continues$/) do
|
43
|
+
expect(@game_over_checker.game_over?(@state)).to eq(false)
|
44
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative '../../lib/threesmodel'
|
2
|
+
|
3
|
+
Before do
|
4
|
+
end
|
5
|
+
|
6
|
+
Given(/^a new game is started$/) do
|
7
|
+
@game_controller = Threesmodel::GameController.new
|
8
|
+
@game_state = @game_controller.start_new_game
|
9
|
+
end
|
10
|
+
|
11
|
+
Then(/^an id is attached to the game$/) do
|
12
|
+
expect(@game_state[:id]).to_not eq(nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
Then(/^the game is not over$/) do
|
16
|
+
expect(@game_state[:game_over]).to eq(false)
|
17
|
+
end
|
18
|
+
|
19
|
+
Then(/^the game board has (\d+) cells filled$/) do |filled_cells|
|
20
|
+
c = []
|
21
|
+
values = @game_state[:game].row_vectors.each{|row|
|
22
|
+
c << row.to_a
|
23
|
+
}
|
24
|
+
c.flatten!
|
25
|
+
d = c.find_all{|item| item > 0}
|
26
|
+
expect(d.size).to eq(9)
|
27
|
+
end
|
28
|
+
|
29
|
+
Then(/^the board contains no other but the following numbers:$/) do |table|
|
30
|
+
data = table.raw[0]
|
31
|
+
c = []
|
32
|
+
values = @game_state[:game].row_vectors.each{|row|
|
33
|
+
c << row.to_a
|
34
|
+
}
|
35
|
+
c.flatten!.uniq!
|
36
|
+
data.each{|value|
|
37
|
+
expect(c.include?(value.to_i)).to eq(true)
|
38
|
+
}
|
39
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'line_folder'
|
2
|
+
class CandidateExtractor
|
3
|
+
|
4
|
+
def initialize(line_folder = LineFolder.new)
|
5
|
+
@line_folder = line_folder
|
6
|
+
end
|
7
|
+
|
8
|
+
def fold_left_candidates(state)
|
9
|
+
candidates = []
|
10
|
+
state.row_vectors.each_index {|i|
|
11
|
+
add_candidate(candidates, i, state.row_vectors[i].to_a)
|
12
|
+
}
|
13
|
+
candidates
|
14
|
+
end
|
15
|
+
|
16
|
+
def fold_right_candidates(state)
|
17
|
+
candidates = []
|
18
|
+
state.row_vectors.each_index {|i|
|
19
|
+
add_candidate(candidates, i, state.row_vectors[i].to_a.reverse)
|
20
|
+
}
|
21
|
+
candidates
|
22
|
+
end
|
23
|
+
|
24
|
+
def fold_up_candidates(state)
|
25
|
+
candidates = []
|
26
|
+
state.column_vectors.each_index {|i|
|
27
|
+
add_candidate(candidates, i, state.column_vectors[i].to_a)
|
28
|
+
}
|
29
|
+
candidates
|
30
|
+
end
|
31
|
+
|
32
|
+
def fold_down_candidates(state)
|
33
|
+
candidates = []
|
34
|
+
state.column_vectors.each_index {|i|
|
35
|
+
add_candidate(candidates, i, state.column_vectors[i].to_a.reverse)
|
36
|
+
}
|
37
|
+
candidates
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_candidate(candidates, index, values)
|
41
|
+
if (@line_folder.can_fold?(values)) then
|
42
|
+
candidates << [index, 3]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class CandidateTranslator
|
2
|
+
|
3
|
+
def translate_left_fold(candidates)
|
4
|
+
candidates
|
5
|
+
end
|
6
|
+
|
7
|
+
def translate_right_fold(candidates)
|
8
|
+
translate(candidates, {[0,3] => [3,0], [1,3] => [2,0], [2,3] => [1,0], [3,3] => [0,0]})
|
9
|
+
end
|
10
|
+
|
11
|
+
def translate_down_fold(candidates)
|
12
|
+
translate(candidates, {[0,3] => [0,0], [1,3] => [0,1], [2,3] => [0,2], [3,3] => [0,3]})
|
13
|
+
end
|
14
|
+
|
15
|
+
def translate_up_fold(candidates)
|
16
|
+
translate(candidates, {[0,3] => [3,3], [1,3] => [3,2], [2,3] => [3,1], [3,3] => [3,0]})
|
17
|
+
end
|
18
|
+
|
19
|
+
def translate(candidates, translation)
|
20
|
+
result = []
|
21
|
+
for candidate in candidates do
|
22
|
+
result << translation[candidate]
|
23
|
+
end
|
24
|
+
result
|
25
|
+
end
|
26
|
+
end
|