twisty_puzzles 0.0.17 → 0.0.19
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 +4 -4
- data/ext/twisty_puzzles/native/native.c +2 -0
- data/ext/twisty_puzzles/native/sticker_cycle.c +196 -0
- data/ext/twisty_puzzles/native/sticker_cycle.h +5 -0
- data/lib/twisty_puzzles/color_scheme.rb +11 -0
- data/lib/twisty_puzzles/cube_state.rb +4 -6
- data/lib/twisty_puzzles/part_cycle_factory.rb +2 -2
- data/lib/twisty_puzzles/rotation.rb +1 -0
- data/lib/twisty_puzzles/skewb_state.rb +0 -11
- data/lib/twisty_puzzles/sticker_cycle.rb +33 -8
- data/lib/twisty_puzzles/version.rb +1 -1
- data/lib/twisty_puzzles.rb +0 -1
- metadata +5 -4
- data/lib/twisty_puzzles/state_helper.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64f6766819367eee6807388d640a4302c3268bcf276a2b52fb4ca94ddbb0ebe2
|
4
|
+
data.tar.gz: 0d60796788d180feb10ad42fa74a6b7535092d5d4040a64375f959ac9a2023da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36cb5bdc5b75cfcb7d0a832cbff120662426ab8dd1fd1120762c3231973f27b706059f6772193ca76403859a3768d847f9ee34fb4012c52deb19226862b8b38c
|
7
|
+
data.tar.gz: 8e6a49720c6219484741a6d5d3248917c02025def3c0eacac34b0de07529b7fe42802fd5473fb782a19ca34f7bbc7319b8ef4ee705bffd135240f9d12f6eb77c
|
@@ -9,6 +9,7 @@
|
|
9
9
|
#include "skewb_coordinate.h"
|
10
10
|
#include "skewb_layer_fingerprint.h"
|
11
11
|
#include "skewb_state.h"
|
12
|
+
#include "sticker_cycle.h"
|
12
13
|
|
13
14
|
VALUE TwistyPuzzlesModule = Qnil;
|
14
15
|
VALUE NativeModule = Qnil;
|
@@ -25,4 +26,5 @@ void Init_native() {
|
|
25
26
|
init_skewb_coordinate_class_under(NativeModule);
|
26
27
|
init_skewb_layer_fingerprint_method_under(NativeModule);
|
27
28
|
init_skewb_state_class_under(NativeModule);
|
29
|
+
init_sticker_cycle_class_under(NativeModule);
|
28
30
|
}
|
@@ -0,0 +1,196 @@
|
|
1
|
+
#include "cube_state.h"
|
2
|
+
|
3
|
+
#include "cube_coordinate.h"
|
4
|
+
#include "cube_state.h"
|
5
|
+
#include "utils.h"
|
6
|
+
|
7
|
+
static ID reverse;
|
8
|
+
|
9
|
+
typedef struct {
|
10
|
+
long cube_size;
|
11
|
+
size_t length;
|
12
|
+
VALUE coordinates;
|
13
|
+
size_t* indices;
|
14
|
+
} StickerCycleData;
|
15
|
+
|
16
|
+
extern const rb_data_type_t StickerCycleData_type;
|
17
|
+
|
18
|
+
#define GetStickerCycleData(obj, data) \
|
19
|
+
do { \
|
20
|
+
TypedData_Get_Struct((obj), StickerCycleData, &StickerCycleData_type, (data)); \
|
21
|
+
} while (0)
|
22
|
+
|
23
|
+
#define GetInitializedStickerCycleData(obj, data) \
|
24
|
+
do { \
|
25
|
+
GetStickerCycleData((obj), (data)); \
|
26
|
+
if (data->indices == NULL) { \
|
27
|
+
rb_raise(rb_eArgError, "Sticker cycle isn't initialized."); \
|
28
|
+
} \
|
29
|
+
} while(0)
|
30
|
+
|
31
|
+
static VALUE StickerCycleClass = Qnil;
|
32
|
+
|
33
|
+
static void StickerCycleData_mark(void* const ptr) {
|
34
|
+
const StickerCycleData* data = ptr;
|
35
|
+
rb_gc_mark(data->coordinates);
|
36
|
+
}
|
37
|
+
|
38
|
+
static void StickerCycleData_free(void* const ptr) {
|
39
|
+
const StickerCycleData* const data = ptr;
|
40
|
+
free(data->indices);
|
41
|
+
free(ptr);
|
42
|
+
}
|
43
|
+
|
44
|
+
static size_t StickerCycleData_size(const void* const ptr) {
|
45
|
+
const StickerCycleData* const data = ptr;
|
46
|
+
return sizeof(StickerCycleData) + num_stickers(data->cube_size) * sizeof(VALUE);
|
47
|
+
}
|
48
|
+
|
49
|
+
const rb_data_type_t StickerCycleData_type = {
|
50
|
+
"TwistyPuzzles::Native::StickerCycleData",
|
51
|
+
{StickerCycleData_mark, StickerCycleData_free, StickerCycleData_size, NULL},
|
52
|
+
NULL, NULL,
|
53
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
54
|
+
};
|
55
|
+
|
56
|
+
static VALUE* malloc_indices(const size_t n) {
|
57
|
+
VALUE* const indices = malloc(n * sizeof(size_t));
|
58
|
+
if (indices == NULL) {
|
59
|
+
rb_raise(rb_eNoMemError, "Allocating sticker cycle failed.");
|
60
|
+
}
|
61
|
+
return indices;
|
62
|
+
}
|
63
|
+
|
64
|
+
static VALUE StickerCycle_alloc(const VALUE klass) {
|
65
|
+
StickerCycleData* data;
|
66
|
+
const VALUE object = TypedData_Make_Struct(klass, StickerCycleData, &StickerCycleData_type, data);
|
67
|
+
data->cube_size = 0;
|
68
|
+
data->length = 0;
|
69
|
+
data->coordinates = Qnil;
|
70
|
+
data->indices = NULL;
|
71
|
+
return object;
|
72
|
+
}
|
73
|
+
|
74
|
+
static VALUE StickerCycle_initialize(const VALUE self, const VALUE cube_size, const VALUE coordinates) {
|
75
|
+
Check_Type(cube_size, T_FIXNUM);
|
76
|
+
Check_Type(coordinates, T_ARRAY);
|
77
|
+
const long checked_cube_size = FIX2INT(cube_size);
|
78
|
+
check_cube_size(checked_cube_size);
|
79
|
+
const size_t n = RARRAY_LEN(coordinates);
|
80
|
+
StickerCycleData* data;
|
81
|
+
GetStickerCycleData(self, data);
|
82
|
+
data->cube_size = checked_cube_size;
|
83
|
+
data->length = n;
|
84
|
+
data->coordinates = coordinates;
|
85
|
+
data->indices = malloc_indices(data->length);
|
86
|
+
for (size_t i = 0; i < n; ++i) {
|
87
|
+
const VALUE coordinate = rb_ary_entry(coordinates, i);
|
88
|
+
data->indices[i] = CubeCoordinate_sticker_index(coordinate, checked_cube_size);
|
89
|
+
}
|
90
|
+
return self;
|
91
|
+
}
|
92
|
+
|
93
|
+
static VALUE StickerCycle_apply_to(const VALUE self, const VALUE cube_state) {
|
94
|
+
const StickerCycleData* sticker_cycle_data;
|
95
|
+
GetInitializedStickerCycleData(self, sticker_cycle_data);
|
96
|
+
|
97
|
+
const CubeStateData* cube_state_data;
|
98
|
+
GetInitializedCubeStateData(cube_state, cube_state_data);
|
99
|
+
|
100
|
+
if (cube_state_data->cube_size != sticker_cycle_data->cube_size) {
|
101
|
+
rb_raise(rb_eArgError, "Cube size of sticker cycle must equal cube size of cube state. Got %ld vs %ld.", sticker_cycle_data->cube_size, cube_state_data->cube_size);
|
102
|
+
}
|
103
|
+
if (sticker_cycle_data->length >= 2) {
|
104
|
+
apply_sticker_cycle(cube_state_data->stickers, sticker_cycle_data->indices, sticker_cycle_data->length, false);
|
105
|
+
}
|
106
|
+
return Qnil;
|
107
|
+
}
|
108
|
+
|
109
|
+
static VALUE StickerCycle_hash(const VALUE self) {
|
110
|
+
const StickerCycleData* data;
|
111
|
+
GetInitializedStickerCycleData(self, data);
|
112
|
+
|
113
|
+
st_index_t hash = rb_hash_start((st_index_t)StickerCycle_hash);
|
114
|
+
hash = rb_hash_uint(hash, data->length);
|
115
|
+
hash = rb_hash_uint(hash, data->cube_size);
|
116
|
+
const size_t n = data->length;
|
117
|
+
for (size_t i = 0; i < n; ++i) {
|
118
|
+
hash = rb_hash_uint(hash, data->indices[i]);
|
119
|
+
}
|
120
|
+
return ST2FIX(rb_hash_end(hash));
|
121
|
+
}
|
122
|
+
|
123
|
+
static VALUE StickerCycle_eql(const VALUE self, const VALUE other) {
|
124
|
+
if (self == other) {
|
125
|
+
return Qtrue;
|
126
|
+
}
|
127
|
+
if (rb_obj_class(self) != rb_obj_class(other)) {
|
128
|
+
return Qfalse;
|
129
|
+
}
|
130
|
+
const StickerCycleData* self_data;
|
131
|
+
GetInitializedStickerCycleData(self, self_data);
|
132
|
+
const StickerCycleData* other_data;
|
133
|
+
GetInitializedStickerCycleData(other, other_data);
|
134
|
+
if (self_data->cube_size != other_data->cube_size) {
|
135
|
+
return Qfalse;
|
136
|
+
}
|
137
|
+
if (self_data->length != other_data->length) {
|
138
|
+
return Qfalse;
|
139
|
+
}
|
140
|
+
const size_t n = self_data->length;
|
141
|
+
for (size_t i = 0; i < n; ++i) {
|
142
|
+
if (self_data->indices[i] != other_data->indices[i]) {
|
143
|
+
return Qfalse;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
return Qtrue;
|
147
|
+
}
|
148
|
+
|
149
|
+
static VALUE StickerCycle_cube_size(const VALUE self) {
|
150
|
+
const StickerCycleData* data;
|
151
|
+
GetInitializedStickerCycleData(self, data);
|
152
|
+
return ST2FIX(data->cube_size);
|
153
|
+
}
|
154
|
+
|
155
|
+
static VALUE StickerCycle_length(const VALUE self) {
|
156
|
+
const StickerCycleData* data;
|
157
|
+
GetInitializedStickerCycleData(self, data);
|
158
|
+
return ST2FIX(data->length);
|
159
|
+
}
|
160
|
+
|
161
|
+
static VALUE StickerCycle_coordinates(const VALUE self) {
|
162
|
+
const StickerCycleData* data;
|
163
|
+
GetInitializedStickerCycleData(self, data);
|
164
|
+
return data->coordinates;
|
165
|
+
}
|
166
|
+
|
167
|
+
static VALUE StickerCycle_inverse(const VALUE self) {
|
168
|
+
const StickerCycleData* data;
|
169
|
+
GetInitializedStickerCycleData(self, data);
|
170
|
+
const long n = data->length;
|
171
|
+
StickerCycleData* inverse_data;
|
172
|
+
const VALUE inverse = TypedData_Make_Struct(rb_obj_class(self), StickerCycleData, &StickerCycleData_type, inverse_data);
|
173
|
+
inverse_data->cube_size = data->cube_size;
|
174
|
+
inverse_data->length = n;
|
175
|
+
inverse_data->indices = malloc_indices(n);
|
176
|
+
inverse_data->coordinates = rb_funcall(data->coordinates, reverse, 0);
|
177
|
+
for (int i = 0; i < n; ++i) {
|
178
|
+
inverse_data->indices[i] = data->indices[n - 1 - i];
|
179
|
+
}
|
180
|
+
return inverse;
|
181
|
+
}
|
182
|
+
|
183
|
+
void init_sticker_cycle_class_under(const VALUE module) {
|
184
|
+
reverse = rb_intern("reverse");
|
185
|
+
StickerCycleClass = rb_define_class_under(module, "StickerCycle", rb_cObject);
|
186
|
+
rb_define_alloc_func(StickerCycleClass, StickerCycle_alloc);
|
187
|
+
rb_define_method(StickerCycleClass, "initialize", StickerCycle_initialize, 2);
|
188
|
+
rb_define_method(StickerCycleClass, "apply_to", StickerCycle_apply_to, 1);
|
189
|
+
rb_define_method(StickerCycleClass, "hash", StickerCycle_hash, 0);
|
190
|
+
rb_define_method(StickerCycleClass, "eql?", StickerCycle_eql, 1);
|
191
|
+
rb_define_alias(StickerCycleClass, "==", "eql?");
|
192
|
+
rb_define_method(StickerCycleClass, "cube_size", StickerCycle_cube_size, 0);
|
193
|
+
rb_define_method(StickerCycleClass, "length", StickerCycle_length, 0);
|
194
|
+
rb_define_method(StickerCycleClass, "coordinates", StickerCycle_coordinates, 0);
|
195
|
+
rb_define_method(StickerCycleClass, "inverse", StickerCycle_inverse, 0);
|
196
|
+
}
|
@@ -28,6 +28,17 @@ module TwistyPuzzles
|
|
28
28
|
@colors_to_face_symbols = face_symbols_to_colors.invert
|
29
29
|
end
|
30
30
|
|
31
|
+
|
32
|
+
def eql?(other)
|
33
|
+
self.class.equal?(other.class) && colors == other.colors
|
34
|
+
end
|
35
|
+
|
36
|
+
alias == eql?
|
37
|
+
|
38
|
+
def hash
|
39
|
+
@hash ||= ([self.class] + colors).hash
|
40
|
+
end
|
41
|
+
|
31
42
|
def color(face_symbol)
|
32
43
|
@face_symbols_to_colors[face_symbol]
|
33
44
|
end
|
@@ -4,7 +4,6 @@ require 'twisty_puzzles/cube'
|
|
4
4
|
require 'twisty_puzzles/cube_constants'
|
5
5
|
require 'twisty_puzzles/coordinate'
|
6
6
|
require 'twisty_puzzles/cube_print_helper'
|
7
|
-
require 'twisty_puzzles/state_helper'
|
8
7
|
require 'twisty_puzzles/utils/array_helper'
|
9
8
|
require 'twisty_puzzles/native'
|
10
9
|
|
@@ -13,7 +12,6 @@ module TwistyPuzzles
|
|
13
12
|
class CubeState
|
14
13
|
include Utils::ArrayHelper
|
15
14
|
include CubePrintHelper
|
16
|
-
include StateHelper
|
17
15
|
include CubeConstants
|
18
16
|
|
19
17
|
def self.check_cube_size(cube_size)
|
@@ -75,6 +73,10 @@ module TwistyPuzzles
|
|
75
73
|
|
76
74
|
alias == eql?
|
77
75
|
|
76
|
+
def hash
|
77
|
+
@hash ||= [self.class, @native].hash
|
78
|
+
end
|
79
|
+
|
78
80
|
def rotation_algorithms
|
79
81
|
Rotation::ALL_ROTATIONS.combination(2).reject do |r0, r1|
|
80
82
|
r0.inverse == r1
|
@@ -85,10 +87,6 @@ module TwistyPuzzles
|
|
85
87
|
rotation_algorithms.any? { |r| r.apply_temporarily_to(self) { |state| state == other } }
|
86
88
|
end
|
87
89
|
|
88
|
-
def hash
|
89
|
-
@hash ||= [self.class, @native].hash
|
90
|
-
end
|
91
|
-
|
92
90
|
# TODO: Get rid of this backwards compatibility artifact
|
93
91
|
def sticker_array(face)
|
94
92
|
raise TypeError unless face.is_a?(Face)
|
@@ -28,7 +28,7 @@ module TwistyPuzzles
|
|
28
28
|
raise TypeError, 'Twists are only supported for edges and corners.'
|
29
29
|
end
|
30
30
|
|
31
|
-
cycles = parts.map { |p| StickerCycle.
|
31
|
+
cycles = parts.map { |p| StickerCycle.from_coordinates(@cube_size, coordinates(p)) }
|
32
32
|
StickerCycles.new(@cube_size, cycles)
|
33
33
|
end
|
34
34
|
|
@@ -49,7 +49,7 @@ module TwistyPuzzles
|
|
49
49
|
check_types(parts, Part)
|
50
50
|
check_type_consistency(parts)
|
51
51
|
part_coordinates = parts.map { |p| coordinates(p) }
|
52
|
-
cycles = part_coordinates.transpose.map { |c| StickerCycle.
|
52
|
+
cycles = part_coordinates.transpose.map { |c| StickerCycle.from_coordinates(@cube_size, c) }
|
53
53
|
StickerCycles.new(@cube_size, cycles)
|
54
54
|
end
|
55
55
|
end
|
@@ -3,14 +3,12 @@
|
|
3
3
|
require 'twisty_puzzles/coordinate'
|
4
4
|
require 'twisty_puzzles/cube'
|
5
5
|
require 'twisty_puzzles/cube_print_helper'
|
6
|
-
require 'twisty_puzzles/state_helper'
|
7
6
|
require 'twisty_puzzles/cube_constants'
|
8
7
|
|
9
8
|
module TwistyPuzzles
|
10
9
|
# Represents the state (i.e. the sticker positions) of a Skewb.
|
11
10
|
class SkewbState
|
12
11
|
include CubePrintHelper
|
13
|
-
include StateHelper
|
14
12
|
include CubeConstants
|
15
13
|
# Pairs of coordinate pairs that should match in case of solved layers.
|
16
14
|
MATCHING_CORNERS =
|
@@ -151,14 +149,5 @@ module TwistyPuzzles
|
|
151
149
|
|
152
150
|
layer_check_neighbors(face).map { |c| self[c] }.uniq.length == 1
|
153
151
|
end
|
154
|
-
|
155
|
-
def rotate_face(face, direction)
|
156
|
-
neighbors = face.neighbors
|
157
|
-
inverse_order_face = face.coordinate_index_close_to(neighbors[0]) <
|
158
|
-
face.coordinate_index_close_to(neighbors[1])
|
159
|
-
direction = direction.inverse if inverse_order_face
|
160
|
-
cycle = SkewbCoordinate.corners_on_face(face)
|
161
|
-
apply_4sticker_cycle(cycle, direction)
|
162
|
-
end
|
163
152
|
end
|
164
153
|
end
|
@@ -10,22 +10,47 @@ module TwistyPuzzles
|
|
10
10
|
class StickerCycle
|
11
11
|
include ReversibleApplyable
|
12
12
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
13
|
+
def self.from_coordinates(cube_size, coordinates)
|
14
|
+
CubeState.check_cube_size(cube_size)
|
15
|
+
raise TypeError unless coordinates.all?(Coordinate)
|
16
|
+
|
17
|
+
new(Native::StickerCycle.new(cube_size, coordinates.map(&:native)))
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(native)
|
21
|
+
raise TypeError unless native.is_a?(Native::StickerCycle)
|
22
|
+
|
23
|
+
@native = native
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :native
|
27
|
+
|
28
|
+
def eql?(other)
|
29
|
+
self.class.equal?(other.class) && @native == other.native
|
16
30
|
end
|
17
31
|
|
18
|
-
|
32
|
+
alias == eql?
|
33
|
+
|
34
|
+
def hash
|
35
|
+
@hash ||= [self.class, @native].hash
|
36
|
+
end
|
37
|
+
|
38
|
+
def cube_size
|
39
|
+
@native.cube_size
|
40
|
+
end
|
41
|
+
|
42
|
+
def length
|
43
|
+
@native.length
|
44
|
+
end
|
19
45
|
|
20
46
|
def apply_to(cube_state)
|
21
47
|
raise TypeError unless cube_state.is_a?(CubeState)
|
22
|
-
raise ArgumentError unless cube_state.n == @cube_size
|
23
48
|
|
24
|
-
cube_state.
|
49
|
+
@native.apply_to(cube_state.native)
|
25
50
|
end
|
26
51
|
|
27
52
|
def inverse
|
28
|
-
StickerCycle.new(@
|
53
|
+
StickerCycle.new(@native.inverse)
|
29
54
|
end
|
30
55
|
end
|
31
56
|
|
@@ -38,7 +63,7 @@ module TwistyPuzzles
|
|
38
63
|
sticker_cycles.each do |c|
|
39
64
|
raise TypeError unless c.is_a?(StickerCycle)
|
40
65
|
|
41
|
-
c.
|
66
|
+
c.native.coordinates.each do |s|
|
42
67
|
raise ArgumentError unless affected_set.add?(s)
|
43
68
|
end
|
44
69
|
end
|
data/lib/twisty_puzzles.rb
CHANGED
@@ -33,7 +33,6 @@ require 'twisty_puzzles/skewb_move'
|
|
33
33
|
require 'twisty_puzzles/skewb_move_parser'
|
34
34
|
require 'twisty_puzzles/skewb_notation'
|
35
35
|
require 'twisty_puzzles/skewb_state'
|
36
|
-
require 'twisty_puzzles/state_helper'
|
37
36
|
require 'twisty_puzzles/sticker_cycle'
|
38
37
|
require 'twisty_puzzles/twisty_puzzles_error'
|
39
38
|
require 'twisty_puzzles/version'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: twisty_puzzles
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.19
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernhard F. Brodowsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
11
|
+
date: 2021-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -196,6 +196,8 @@ files:
|
|
196
196
|
- ext/twisty_puzzles/native/skewb_layer_fingerprint.h
|
197
197
|
- ext/twisty_puzzles/native/skewb_state.c
|
198
198
|
- ext/twisty_puzzles/native/skewb_state.h
|
199
|
+
- ext/twisty_puzzles/native/sticker_cycle.c
|
200
|
+
- ext/twisty_puzzles/native/sticker_cycle.h
|
199
201
|
- ext/twisty_puzzles/native/utils.c
|
200
202
|
- ext/twisty_puzzles/native/utils.h
|
201
203
|
- lib/twisty_puzzles.rb
|
@@ -231,7 +233,6 @@ files:
|
|
231
233
|
- lib/twisty_puzzles/skewb_move_parser.rb
|
232
234
|
- lib/twisty_puzzles/skewb_notation.rb
|
233
235
|
- lib/twisty_puzzles/skewb_state.rb
|
234
|
-
- lib/twisty_puzzles/state_helper.rb
|
235
236
|
- lib/twisty_puzzles/sticker_cycle.rb
|
236
237
|
- lib/twisty_puzzles/twisty_puzzles_error.rb
|
237
238
|
- lib/twisty_puzzles/utils.rb
|
@@ -260,7 +261,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
260
261
|
- !ruby/object:Gem::Version
|
261
262
|
version: '0'
|
262
263
|
requirements: []
|
263
|
-
rubygems_version: 3.2.
|
264
|
+
rubygems_version: 3.2.22
|
264
265
|
signing_key:
|
265
266
|
specification_version: 4
|
266
267
|
summary: Gem for my cube_trainer rails app. Some things are better left in a separate
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'twisty_puzzles/abstract_direction'
|
4
|
-
|
5
|
-
module TwistyPuzzles
|
6
|
-
# Common utilities for different puzzle states.
|
7
|
-
# TODO: Remove
|
8
|
-
module StateHelper
|
9
|
-
def apply_sticker_cycle(cycle)
|
10
|
-
last_sticker = self[cycle[-1]]
|
11
|
-
(cycle.length - 1).downto(1) do |i|
|
12
|
-
self[cycle[i]] = self[cycle[i - 1]]
|
13
|
-
end
|
14
|
-
self[cycle[0]] = last_sticker
|
15
|
-
end
|
16
|
-
|
17
|
-
def apply_4sticker_cycle(cycle, direction)
|
18
|
-
raise ArgumentError unless cycle.length == 4
|
19
|
-
raise TypeError unless direction.is_a?(AbstractDirection)
|
20
|
-
|
21
|
-
if direction.double_move?
|
22
|
-
apply_sticker_cycle([cycle[0], cycle[2]])
|
23
|
-
apply_sticker_cycle([cycle[1], cycle[3]])
|
24
|
-
else
|
25
|
-
# Note that we cannot do reverse! because the values are cached.
|
26
|
-
actual_cycle = direction.value == 3 ? cycle.reverse : cycle
|
27
|
-
apply_sticker_cycle(actual_cycle)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|