1 /*****************************************************************************
2 * puzzle_mgt.c : Puzzle game filter - game management
3 *****************************************************************************
4 * Copyright (C) 2005-2009 VLC authors and VideoLAN
5 * Copyright (C) 2013 Vianney Boyer
8 * Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
9 * Vianney Boyer <vlcvboyer -at- gmail -dot- com>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_filter.h>
38 #include <vlc_picture.h>
41 #include "filter_picture.h"
43 #include "puzzle_bezier.h"
44 #include "puzzle_lib.h"
45 #include "puzzle_pce.h"
46 #include "puzzle_mgt.h"
48 /*****************************************************************************
49 * puzzle_bake: compute general puzzle data and allocate structures
50 *****************************************************************************/
51 int puzzle_bake( filter_t
*p_filter
, picture_t
*p_pic_out
, picture_t
*p_pic_in
)
53 filter_sys_t
*p_sys
= p_filter
->p_sys
;
56 puzzle_free_ps_puzzle_array ( p_filter
);
57 puzzle_free_ps_pieces_shapes ( p_filter
);
58 puzzle_free_ps_pieces ( p_filter
);
60 p_sys
->s_allocated
.i_rows
= p_sys
->s_current_param
.i_rows
;
61 p_sys
->s_allocated
.i_cols
= p_sys
->s_current_param
.i_cols
;
62 p_sys
->s_allocated
.i_planes
= p_sys
->s_current_param
.i_planes
;
63 p_sys
->s_allocated
.i_piece_types
= ((p_sys
->s_current_param
.b_advanced
)?PIECE_TYPE_NBR
:0);
64 p_sys
->s_allocated
.i_pieces_nbr
= p_sys
->s_allocated
.i_rows
* p_sys
->s_allocated
.i_cols
;
65 p_sys
->s_allocated
.b_preview
= p_sys
->s_current_param
.b_preview
;
66 p_sys
->s_allocated
.i_preview_size
= p_sys
->s_current_param
.i_preview_size
;
67 p_sys
->s_allocated
.i_border
= p_sys
->s_current_param
.i_border
;
68 p_sys
->s_allocated
.b_blackslot
= p_sys
->s_current_param
.b_blackslot
;
69 p_sys
->s_allocated
.b_near
= p_sys
->s_current_param
.b_near
;
70 p_sys
->s_allocated
.i_shape_size
= p_sys
->s_current_param
.i_shape_size
;
71 p_sys
->s_allocated
.b_advanced
= p_sys
->s_current_param
.b_advanced
;
72 p_sys
->s_allocated
.i_auto_shuffle_speed
= p_sys
->s_current_param
.i_auto_shuffle_speed
;
73 p_sys
->s_allocated
.i_auto_solve_speed
= p_sys
->s_current_param
.i_auto_solve_speed
;
74 p_sys
->s_allocated
.i_rotate
= p_sys
->s_current_param
.i_rotate
;
76 p_sys
->ps_puzzle_array
= malloc( sizeof( puzzle_array_t
** ) * (p_sys
->s_allocated
.i_rows
+ 1));
77 if( !p_sys
->ps_puzzle_array
)
80 for (int32_t r
=0; r
< p_sys
->s_allocated
.i_rows
+ 1; r
++) {
81 p_sys
->ps_puzzle_array
[r
] = malloc( sizeof( puzzle_array_t
* ) * (p_sys
->s_allocated
.i_cols
+ 1));
82 if( !p_sys
->ps_puzzle_array
[r
] )
84 for (int32_t c
=0; c
< p_sys
->s_allocated
.i_cols
+ 1; c
++) {
85 p_sys
->ps_puzzle_array
[r
][c
] = malloc( sizeof( puzzle_array_t
) * p_sys
->s_allocated
.i_planes
);
86 if( !p_sys
->ps_puzzle_array
[r
][c
] )
91 p_sys
->ps_desk_planes
= malloc( sizeof( puzzle_plane_t
) * p_sys
->s_allocated
.i_planes
);
92 if( !p_sys
->ps_desk_planes
)
94 p_sys
->ps_pict_planes
= malloc( sizeof( puzzle_plane_t
) * p_sys
->s_allocated
.i_planes
);
95 if( !p_sys
->ps_pict_planes
)
98 for (uint8_t i_plane
= 0; i_plane
< p_sys
->s_allocated
.i_planes
; i_plane
++) {
99 p_sys
->ps_desk_planes
[i_plane
].i_lines
= p_pic_out
->p
[i_plane
].i_visible_lines
;
100 p_sys
->ps_desk_planes
[i_plane
].i_pitch
= p_pic_out
->p
[i_plane
].i_pitch
;
101 p_sys
->ps_desk_planes
[i_plane
].i_visible_pitch
= p_pic_out
->p
[i_plane
].i_visible_pitch
;
102 p_sys
->ps_desk_planes
[i_plane
].i_pixel_pitch
= p_pic_out
->p
[i_plane
].i_pixel_pitch
;
103 p_sys
->ps_desk_planes
[i_plane
].i_width
= p_pic_out
->p
[i_plane
].i_visible_pitch
/ p_pic_out
->p
[i_plane
].i_pixel_pitch
;
105 p_sys
->ps_desk_planes
[i_plane
].i_preview_width
= p_sys
->ps_desk_planes
[i_plane
].i_width
* p_sys
->s_current_param
.i_preview_size
/ 100;
106 p_sys
->ps_desk_planes
[i_plane
].i_preview_lines
= p_sys
->ps_desk_planes
[i_plane
].i_lines
* p_sys
->s_current_param
.i_preview_size
/ 100;
108 p_sys
->ps_desk_planes
[i_plane
].i_border_width
= p_sys
->ps_desk_planes
[i_plane
].i_width
* p_sys
->s_current_param
.i_border
/ 2 / 100;
109 p_sys
->ps_desk_planes
[i_plane
].i_border_lines
= p_sys
->ps_desk_planes
[i_plane
].i_lines
* p_sys
->s_current_param
.i_border
/ 2 / 100;
111 p_sys
->ps_desk_planes
[i_plane
].i_pce_max_width
= (( p_sys
->ps_desk_planes
[i_plane
].i_width
112 - 2 * p_sys
->ps_desk_planes
[i_plane
].i_border_width
) + p_sys
->s_allocated
.i_cols
- 1 ) / p_sys
->s_allocated
.i_cols
;
113 p_sys
->ps_desk_planes
[i_plane
].i_pce_max_lines
= (( p_sys
->ps_desk_planes
[i_plane
].i_lines
114 - 2 * p_sys
->ps_desk_planes
[i_plane
].i_border_lines
) + p_sys
->s_allocated
.i_rows
- 1 ) / p_sys
->s_allocated
.i_rows
;
116 p_sys
->ps_pict_planes
[i_plane
].i_lines
= p_pic_in
->p
[i_plane
].i_visible_lines
;
117 p_sys
->ps_pict_planes
[i_plane
].i_pitch
= p_pic_in
->p
[i_plane
].i_pitch
;
118 p_sys
->ps_pict_planes
[i_plane
].i_visible_pitch
= p_pic_in
->p
[i_plane
].i_visible_pitch
;
119 p_sys
->ps_pict_planes
[i_plane
].i_pixel_pitch
= p_pic_in
->p
[i_plane
].i_pixel_pitch
;
120 p_sys
->ps_pict_planes
[i_plane
].i_width
= p_pic_in
->p
[i_plane
].i_visible_pitch
/ p_pic_in
->p
[i_plane
].i_pixel_pitch
;
122 p_sys
->ps_pict_planes
[i_plane
].i_preview_width
= p_sys
->ps_pict_planes
[i_plane
].i_width
* p_sys
->s_current_param
.i_preview_size
/ 100;
123 p_sys
->ps_pict_planes
[i_plane
].i_preview_lines
= p_sys
->ps_pict_planes
[i_plane
].i_lines
* p_sys
->s_current_param
.i_preview_size
/ 100;
125 p_sys
->ps_pict_planes
[i_plane
].i_border_width
= p_sys
->ps_pict_planes
[i_plane
].i_width
* p_sys
->s_current_param
.i_border
/ 2 / 100;
126 p_sys
->ps_pict_planes
[i_plane
].i_border_lines
= p_sys
->ps_pict_planes
[i_plane
].i_lines
* p_sys
->s_current_param
.i_border
/ 2 / 100;
128 p_sys
->ps_pict_planes
[i_plane
].i_pce_max_width
= (( p_sys
->ps_desk_planes
[i_plane
].i_width
129 - 2 * p_sys
->ps_pict_planes
[i_plane
].i_border_width
) + p_sys
->s_allocated
.i_cols
- 1 ) / p_sys
->s_allocated
.i_cols
;
130 p_sys
->ps_pict_planes
[i_plane
].i_pce_max_lines
= (( p_sys
->ps_pict_planes
[i_plane
].i_lines
131 - 2 * p_sys
->ps_pict_planes
[i_plane
].i_border_lines
) + p_sys
->s_allocated
.i_rows
- 1 ) / p_sys
->s_allocated
.i_rows
;
133 for (int32_t r
= 0; r
< p_sys
->s_allocated
.i_rows
; r
++)
134 for (int32_t c
= 0; c
< p_sys
->s_allocated
.i_cols
; c
++) {
136 p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_y
= p_sys
->ps_pict_planes
[i_plane
].i_border_lines
;
138 p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_x
= p_sys
->ps_pict_planes
[i_plane
].i_border_width
;
139 p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_width
=
140 (p_sys
->ps_pict_planes
[i_plane
].i_width
- p_sys
->ps_pict_planes
[i_plane
].i_border_width
141 - p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_x
) / ( p_sys
->s_allocated
.i_cols
- c
);
142 p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_lines
=
143 (p_sys
->ps_pict_planes
[i_plane
].i_lines
- p_sys
->ps_pict_planes
[i_plane
].i_border_lines
144 - p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_y
) / ( p_sys
->s_allocated
.i_rows
- r
);
145 p_sys
->ps_puzzle_array
[r
][c
+ 1][i_plane
].i_x
=
146 p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_x
+ p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_width
;
147 p_sys
->ps_puzzle_array
[r
+ 1][c
][i_plane
].i_y
=
148 p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_y
+ p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_lines
;
152 p_sys
->i_magnet_accuracy
= ( p_sys
->s_current_param
.i_pict_width
/ 50) + 3;
154 if (p_sys
->s_current_param
.b_advanced
&& p_sys
->s_allocated
.i_shape_size
!= 0) {
155 i_ret
= puzzle_bake_pieces_shapes ( p_filter
);
156 if (i_ret
!= VLC_SUCCESS
)
160 i_ret
= puzzle_bake_piece ( p_filter
);
161 if (i_ret
!= VLC_SUCCESS
)
164 if ( (p_sys
->pi_order
!= NULL
) && (p_sys
->ps_desk_planes
!= NULL
) && (p_sys
->ps_pict_planes
!= NULL
)
165 && (p_sys
->ps_puzzle_array
!= NULL
) && (p_sys
->ps_pieces
!= NULL
) )
166 p_sys
->b_init
= true;
168 if ( (p_sys
->ps_pieces_shapes
== NULL
) && (p_sys
->s_current_param
.b_advanced
)
169 && (p_sys
->s_current_param
.i_shape_size
!= 0) )
170 p_sys
->b_init
= false;
175 void puzzle_free_ps_puzzle_array( filter_t
*p_filter
)
177 filter_sys_t
*p_sys
= p_filter
->p_sys
;
179 if (p_sys
->ps_puzzle_array
!= NULL
) {
180 for (int32_t r
=0; r
< p_sys
->s_allocated
.i_rows
+ 1; r
++) {
181 for (int32_t c
=0; c
< p_sys
->s_allocated
.i_cols
+ 1; c
++)
182 free( p_sys
->ps_puzzle_array
[r
][c
] );
183 free( p_sys
->ps_puzzle_array
[r
] );
185 free( p_sys
->ps_puzzle_array
);
187 p_sys
->ps_puzzle_array
= NULL
;
189 free ( p_sys
->ps_desk_planes
);
190 p_sys
->ps_desk_planes
= NULL
;
192 free ( p_sys
->ps_pict_planes
);
193 p_sys
->ps_pict_planes
= NULL
;
198 /*****************************************************************************
199 * puzzle_bake_piece: compute data dedicated to each piece
200 *****************************************************************************/
201 int puzzle_bake_piece( filter_t
*p_filter
)
203 int i_ret
= puzzle_allocate_ps_pieces( p_filter
);
204 if (i_ret
!= VLC_SUCCESS
)
207 filter_sys_t
*p_sys
= p_filter
->p_sys
;
209 /* generates random pi_order array */
210 i_ret
= puzzle_shuffle( p_filter
);
211 if (i_ret
!= VLC_SUCCESS
)
215 for (int32_t row
= 0; row
< p_sys
->s_allocated
.i_rows
; row
++) {
216 for (int32_t col
= 0; col
< p_sys
->s_allocated
.i_cols
; col
++) {
220 if (p_sys
->pi_order
!= NULL
) {
221 orow
= p_sys
->pi_order
[i
] / (p_sys
->s_allocated
.i_cols
);
222 ocol
= p_sys
->pi_order
[i
] % (p_sys
->s_allocated
.i_cols
);
225 p_sys
->ps_pieces
[i
].i_original_row
= orow
;
226 p_sys
->ps_pieces
[i
].i_original_col
= ocol
;
228 /* set bottom and right shapes */
229 p_sys
->ps_pieces
[i
].i_left_shape
= 0;
230 p_sys
->ps_pieces
[i
].i_top_shape
= 2;
231 p_sys
->ps_pieces
[i
].i_btm_shape
= 4;
232 p_sys
->ps_pieces
[i
].i_right_shape
= 6;
234 if (p_sys
->s_allocated
.i_shape_size
> 0) {
236 if (orow
< p_sys
->s_allocated
.i_rows
- 1)
237 p_sys
->ps_pieces
[i
].i_btm_shape
= 4 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
239 if (ocol
< p_sys
->s_allocated
.i_cols
- 1)
240 p_sys
->ps_pieces
[i
].i_right_shape
= 6 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
244 p_sys
->ps_pieces
[i
].i_actual_angle
= 0;
245 p_sys
->ps_pieces
[i
].b_overlap
= false;
246 p_sys
->ps_pieces
[i
].i_actual_mirror
= +1;
247 p_sys
->ps_pieces
[i
].b_finished
= ((ocol
== col
) && (orow
== row
));
248 p_sys
->ps_pieces
[i
].i_group_ID
= i
;
250 /* add small random offset to location */
251 int32_t i_rand_x
= 0;
252 int32_t i_rand_y
= 0;
253 if (p_sys
->s_current_param
.b_advanced
) {
254 i_rand_x
= (( (unsigned) vlc_mrand48()) % ( p_sys
->ps_desk_planes
[0].i_pce_max_width
+ 1 ) ) - (int32_t) p_sys
->ps_desk_planes
[0].i_pce_max_width
/ 2;
255 i_rand_y
= (( (unsigned) vlc_mrand48()) % ( p_sys
->ps_desk_planes
[0].i_pce_max_lines
+ 1 ) ) - (int32_t) p_sys
->ps_desk_planes
[0].i_pce_max_lines
/ 2;
258 /* copy related puzzle data to piece data */
259 if (p_sys
->ps_puzzle_array
!= NULL
) {
260 for (uint8_t i_plane
= 0; i_plane
< p_sys
->s_allocated
.i_planes
; i_plane
++) {
262 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[i_plane
].i_width
= p_sys
->ps_puzzle_array
[row
][col
][i_plane
].i_width
;
263 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[i_plane
].i_lines
= p_sys
->ps_puzzle_array
[row
][col
][i_plane
].i_lines
;
264 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[i_plane
].i_original_x
= p_sys
->ps_puzzle_array
[orow
][ocol
][i_plane
].i_x
;
265 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[i_plane
].i_original_y
= p_sys
->ps_puzzle_array
[orow
][ocol
][i_plane
].i_y
;
266 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[i_plane
].i_actual_x
= p_sys
->ps_puzzle_array
[row
][col
][i_plane
].i_x
+ i_rand_x
*
267 p_sys
->ps_desk_planes
[i_plane
].i_width
/ p_sys
->ps_desk_planes
[0].i_width
;
268 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[i_plane
].i_actual_y
= p_sys
->ps_puzzle_array
[row
][col
][i_plane
].i_y
+ i_rand_y
*
269 p_sys
->ps_desk_planes
[i_plane
].i_lines
/ p_sys
->ps_desk_planes
[0].i_lines
;
273 p_sys
->ps_pieces
[i
].i_OLx
= p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_original_x
;
274 p_sys
->ps_pieces
[i
].i_OTy
= p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_original_y
;
275 p_sys
->ps_pieces
[i
].i_ORx
= p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_original_x
+ p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_width
- 1;
276 p_sys
->ps_pieces
[i
].i_OBy
= p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_original_y
+ p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_lines
- 1;
278 puzzle_calculate_corners( p_filter
, i
);
286 /* left and top shapes are based on negative right and bottom ones */
287 puzzle_set_left_top_shapes( p_filter
);
289 /* add random rotation to each piece */
290 puzzle_random_rotate( p_filter
);
295 /*****************************************************************************
296 * puzzle_set_left_top_shapes: Set the shape ID to be used for top and left
297 * edges of each piece. Those ID will be set to
298 * be the negative of bottom or right of adjacent
300 *****************************************************************************/
301 void puzzle_set_left_top_shapes( filter_t
*p_filter
)
303 filter_sys_t
*p_sys
= p_filter
->p_sys
;
304 /* for each piece on the desk... */
305 for (uint16_t i_pce_B
=0; i_pce_B
< p_sys
->s_allocated
.i_pieces_nbr
; i_pce_B
++)
306 /* ...search adjacent piece */
307 for (uint16_t i_pce_A
=0; i_pce_A
< p_sys
->s_allocated
.i_pieces_nbr
; i_pce_A
++)
309 if ( ( p_sys
->ps_pieces
[i_pce_A
].i_original_row
== p_sys
->ps_pieces
[i_pce_B
].i_original_row
)
310 && ( p_sys
->ps_pieces
[i_pce_A
].i_original_col
== p_sys
->ps_pieces
[i_pce_B
].i_original_col
-1 ) )
311 /* left shape is based on negative (invert ID LSB) right one */
312 p_sys
->ps_pieces
[i_pce_B
].i_left_shape
= (p_sys
->ps_pieces
[i_pce_A
].i_right_shape
- 6 ) ^ 0x01;
314 if ( ( p_sys
->ps_pieces
[i_pce_A
].i_original_row
== p_sys
->ps_pieces
[i_pce_B
].i_original_row
- 1 )
315 && ( p_sys
->ps_pieces
[i_pce_A
].i_original_col
== p_sys
->ps_pieces
[i_pce_B
].i_original_col
) )
316 /* top shape is based on negative of bottom one
317 * top ID = bottom ID - 2
318 * negative ID = invert LSB
320 p_sys
->ps_pieces
[i_pce_B
].i_top_shape
= (p_sys
->ps_pieces
[i_pce_A
].i_btm_shape
- 2 ) ^ 0x01;
324 void puzzle_random_rotate( filter_t
*p_filter
)
326 filter_sys_t
*p_sys
= p_filter
->p_sys
;
327 /* add random rotation to each piece */
328 for (uint32_t i
= 0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++)
330 p_sys
->ps_pieces
[i
].i_actual_angle
= 0;
331 p_sys
->ps_pieces
[i
].i_actual_mirror
= +1;
333 switch ( p_sys
->s_current_param
.i_rotate
)
336 puzzle_rotate_pce( p_filter
, i
, (( (unsigned) vlc_mrand48()) % ( 2 ) ) * 2, p_sys
->ps_pieces
[i
].i_center_x
, p_sys
->ps_pieces
[i
].i_center_y
, false );
339 puzzle_rotate_pce( p_filter
, i
, (( (unsigned) vlc_mrand48()) % ( 4 ) ), p_sys
->ps_pieces
[i
].i_center_x
, p_sys
->ps_pieces
[i
].i_center_y
, false );
342 puzzle_rotate_pce( p_filter
, i
, (( (unsigned) vlc_mrand48()) % ( 8 ) ), p_sys
->ps_pieces
[i
].i_center_x
, p_sys
->ps_pieces
[i
].i_center_y
, false );
345 puzzle_calculate_corners( p_filter
, i
);
349 void puzzle_free_ps_pieces( filter_t
*p_filter
)
351 filter_sys_t
*p_sys
= p_filter
->p_sys
;
353 if (p_sys
->ps_pieces
!= NULL
) {
354 for (uint32_t i_pce
= 0; i_pce
< p_sys
->s_allocated
.i_pieces_nbr
; i_pce
++)
355 free( p_sys
->ps_pieces
[i_pce
].ps_piece_in_plane
);
356 free( p_sys
->ps_pieces
);
358 p_sys
->ps_pieces
= NULL
;
360 free( p_sys
->pi_order
);
361 p_sys
->pi_order
= NULL
;
363 free( p_sys
->ps_pieces_tmp
);
364 p_sys
->ps_pieces_tmp
= NULL
;
366 free( p_sys
->pi_group_qty
);
367 p_sys
->pi_group_qty
= NULL
;
372 int puzzle_allocate_ps_pieces( filter_t
*p_filter
)
374 filter_sys_t
*p_sys
= p_filter
->p_sys
;
375 puzzle_free_ps_pieces(p_filter
);
376 p_sys
->s_allocated
.i_pieces_nbr
= p_sys
->s_allocated
.i_rows
* p_sys
->s_allocated
.i_cols
;
377 p_sys
->ps_pieces
= malloc( sizeof( piece_t
) * p_sys
->s_allocated
.i_pieces_nbr
);
378 if( !p_sys
->ps_pieces
)
380 for (uint32_t p
= 0; p
< p_sys
->s_allocated
.i_pieces_nbr
; p
++) {
381 p_sys
->ps_pieces
[p
].ps_piece_in_plane
= malloc( sizeof( piece_in_plane_t
) * p_sys
->s_allocated
.i_planes
);
382 if( !p_sys
->ps_pieces
[p
].ps_piece_in_plane
) {
383 for (uint32_t i
=0;i
<p
;i
++)
384 free(p_sys
->ps_pieces
[i
].ps_piece_in_plane
);
385 free(p_sys
->ps_pieces
);
386 p_sys
->ps_pieces
= NULL
;
391 p_sys
->ps_pieces_tmp
= malloc( sizeof( piece_t
) * p_sys
->s_allocated
.i_pieces_nbr
);
392 if( !p_sys
->ps_pieces_tmp
) {
393 for (uint32_t i
=0;i
<p_sys
->s_allocated
.i_pieces_nbr
;i
++)
394 free(p_sys
->ps_pieces
[i
].ps_piece_in_plane
);
395 free(p_sys
->ps_pieces
);
396 p_sys
->ps_pieces
= NULL
;
399 p_sys
->pi_group_qty
= malloc( sizeof( int32_t ) * (p_sys
->s_allocated
.i_pieces_nbr
));
400 if( !p_sys
->pi_group_qty
) {
401 for (uint32_t i
=0;i
<p_sys
->s_allocated
.i_pieces_nbr
;i
++)
402 free(p_sys
->ps_pieces
[i
].ps_piece_in_plane
);
403 free(p_sys
->ps_pieces
);
404 p_sys
->ps_pieces
= NULL
;
405 free(p_sys
->ps_pieces_tmp
);
406 p_sys
->ps_pieces_tmp
= NULL
;
412 bool puzzle_is_valid( filter_sys_t
*p_sys
, int32_t *pi_pce_lst
)
414 const int32_t i_count
= p_sys
->s_allocated
.i_pieces_nbr
;
416 if( !p_sys
->s_current_param
.b_blackslot
)
420 for( int32_t i
= 0; i
< i_count
; i
++ ) {
421 if( pi_pce_lst
[i
] == i_count
- 1 ) {
422 d
+= i
/ p_sys
->s_allocated
.i_cols
+ 1;
425 for( int32_t j
= i
+1; j
< i_count
; j
++ ) {
426 if( pi_pce_lst
[j
] == i_count
- 1 )
428 if( pi_pce_lst
[i
] > pi_pce_lst
[j
] )
435 int puzzle_shuffle( filter_t
*p_filter
)
437 filter_sys_t
*p_sys
= p_filter
->p_sys
;
439 int32_t i_pieces_nbr
= p_sys
->s_allocated
.i_pieces_nbr
;
443 int i_ret
= puzzle_generate_rand_pce_list( p_filter
, &p_sys
->pi_order
);
444 if (i_ret
!= VLC_SUCCESS
)
446 } while( puzzle_is_finished( p_sys
, p_sys
->pi_order
) || !puzzle_is_valid( p_sys
, p_sys
->pi_order
) );
449 if( p_sys
->s_current_param
.b_blackslot
) {
450 for( int32_t i
= 0; i
< i_pieces_nbr
; i
++ )
451 if( p_sys
->pi_order
[i
] == i_pieces_nbr
- 1 ) {
452 p_sys
->i_selected
= i
;
457 p_sys
->i_selected
= NO_PCE
;
460 p_sys
->b_shuffle_rqst
= false;
461 p_sys
->b_finished
= false;
466 int puzzle_generate_rand_pce_list( filter_t
*p_filter
, int32_t **pi_pce_lst
)
468 filter_sys_t
*p_sys
= p_filter
->p_sys
;
469 int32_t i_pieces_nbr
= p_sys
->s_allocated
.i_pieces_nbr
;
472 *pi_pce_lst
= calloc( i_pieces_nbr
, sizeof(**pi_pce_lst
) );
476 for( int32_t i
= 0; i
< i_pieces_nbr
; i
++ )
477 (*pi_pce_lst
)[i
] = NO_PCE
;
479 for( int32_t c
= 0; c
< i_pieces_nbr
; ) {
480 int32_t i
= ((unsigned)vlc_mrand48()) % i_pieces_nbr
;
481 if( (*pi_pce_lst
)[i
] == NO_PCE
)
482 (*pi_pce_lst
)[i
] = c
++;
487 bool puzzle_is_finished( filter_sys_t
*p_sys
, int32_t *pi_pce_lst
)
489 for( uint32_t i
= 0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++ )
490 if( (int32_t)i
!= pi_pce_lst
[i
] )
496 int puzzle_piece_foreground( filter_t
*p_filter
, int32_t i_piece
) {
497 filter_sys_t
*p_sys
= p_filter
->p_sys
;
498 piece_t
*ps_pieces_tmp
; /* list [piece] of pieces data. Sort as per layers */
499 uint32_t i_group_ID
= p_sys
->ps_pieces
[i_piece
].i_group_ID
;
501 ps_pieces_tmp
= malloc( sizeof( piece_t
) * p_sys
->s_allocated
.i_pieces_nbr
);
507 memcpy( &ps_pieces_tmp
[j
], &p_sys
->ps_pieces
[i_piece
], sizeof(piece_t
) );
510 for (uint32_t i
= 0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++) {
511 if ( ( p_sys
->ps_pieces
[i
].i_group_ID
== i_group_ID
) && ( (int32_t)i
!= i_piece
) ) {
512 memcpy( &ps_pieces_tmp
[j
], &p_sys
->ps_pieces
[i
], sizeof(piece_t
));
516 for (uint32_t i
= 0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++) {
517 if ( p_sys
->ps_pieces
[i
].i_group_ID
!= i_group_ID
) {
518 memcpy( &ps_pieces_tmp
[j
], &p_sys
->ps_pieces
[i
], sizeof(piece_t
));
523 free( p_filter
->p_sys
->ps_pieces
);
524 p_filter
->p_sys
->ps_pieces
= ps_pieces_tmp
;
529 void puzzle_count_pce_group( filter_t
*p_filter
) { /* count pce in each group */
530 filter_sys_t
*p_sys
= p_filter
->p_sys
;
532 memset ( p_sys
->pi_group_qty
, 0, sizeof( int32_t ) * (p_sys
->s_allocated
.i_pieces_nbr
) );
533 for (uint32_t i_pce
= 0; i_pce
< p_sys
->s_allocated
.i_pieces_nbr
; i_pce
++)
534 p_sys
->pi_group_qty
[p_sys
->ps_pieces
[i_pce
].i_group_ID
]++;
537 /*****************************************************************************
538 * puzzle_solve_pces_group: check if pieces are close together
539 * and then combine in a group
540 *****************************************************************************/
541 void puzzle_solve_pces_group( filter_t
*p_filter
) {
542 filter_sys_t
*p_sys
= p_filter
->p_sys
;
545 p_sys
->i_solve_grp_loop
++;
546 p_sys
->i_solve_grp_loop
%= p_sys
->s_allocated
.i_pieces_nbr
;
548 int32_t i_piece_A
= p_sys
->i_solve_grp_loop
;
549 piece_t
*ps_piece_A
= &p_sys
->ps_pieces
[i_piece_A
];
551 for (uint32_t i_piece_B
= 0; i_piece_B
< p_sys
->s_allocated
.i_pieces_nbr
; i_piece_B
++)
553 piece_t
*ps_piece_B
= &p_sys
->ps_pieces
[i_piece_B
];
555 if ( ps_piece_A
->i_actual_angle
!= ps_piece_B
->i_actual_angle
|| ps_piece_A
->i_actual_mirror
!= ps_piece_B
->i_actual_mirror
)
558 if ( (ps_piece_B
->i_group_ID
!= p_sys
->ps_pieces
[i_piece_A
].i_group_ID
) )
560 if ( abs(ps_piece_A
->i_OTy
- ps_piece_B
->i_OTy
)<3)
562 if ( abs( ps_piece_A
->i_ORx
- ps_piece_B
->i_OLx
+ 1 ) < 3
563 && abs( ps_piece_A
->i_TRx
- ps_piece_B
->i_TLx
+ 1 ) < p_sys
->i_magnet_accuracy
564 && abs( ps_piece_A
->i_TRy
- ps_piece_B
->i_TLy
) < p_sys
->i_magnet_accuracy
565 && abs( ps_piece_A
->i_BRx
- ps_piece_B
->i_BLx
+ 1 ) < p_sys
->i_magnet_accuracy
566 && abs( ps_piece_A
->i_BRy
- ps_piece_B
->i_BLy
) < p_sys
->i_magnet_accuracy
)
568 i_dx
= ps_piece_A
->i_TRx
- ps_piece_B
->i_TLx
+ ps_piece_A
->i_step_x_x
;
569 i_dy
= ps_piece_A
->i_TRy
- ps_piece_B
->i_TLy
;
571 if (!ps_piece_B
->b_finished
)
572 puzzle_move_group( p_filter
, i_piece_B
, i_dx
, i_dy
);
574 puzzle_move_group( p_filter
, i_piece_A
, -i_dx
, -i_dy
);
576 uint32_t i_group_ID
= ps_piece_B
->i_group_ID
;
577 for (uint32_t i_for
= 0; i_for
< p_sys
->s_allocated
.i_pieces_nbr
; i_for
++)
578 if ( p_sys
->ps_pieces
[i_for
].i_group_ID
== i_group_ID
)
579 p_sys
->ps_pieces
[i_for
].i_group_ID
= p_sys
->ps_pieces
[i_piece_A
].i_group_ID
;
582 else if ( abs(ps_piece_A
->i_OLx
- ps_piece_B
->i_OLx
) < 3 )
584 if ( abs(ps_piece_A
->i_OBy
- ps_piece_B
->i_OTy
+ 1 ) < 3
585 && abs( ps_piece_B
->i_TLx
- ps_piece_A
->i_BLx
) < p_sys
->i_magnet_accuracy
586 && abs( ps_piece_B
->i_TLy
- 1 - ps_piece_A
->i_BLy
) < p_sys
->i_magnet_accuracy
587 && abs( ps_piece_B
->i_TRx
- ps_piece_A
->i_BRx
) < p_sys
->i_magnet_accuracy
588 && abs( ps_piece_B
->i_TRy
- 1 - ps_piece_A
->i_BRy
) < p_sys
->i_magnet_accuracy
)
591 i_dx
= ps_piece_A
->i_BLx
- ps_piece_B
->i_TLx
;
592 i_dy
= ps_piece_A
->i_BLy
- ps_piece_B
->i_TLy
+ ps_piece_A
->i_step_y_y
;
594 if (!ps_piece_B
->b_finished
)
595 puzzle_move_group( p_filter
, i_piece_B
, i_dx
, i_dy
);
597 puzzle_move_group( p_filter
, i_piece_A
, -i_dx
, -i_dy
);
599 uint32_t i_group_ID
= ps_piece_B
->i_group_ID
;
600 for (uint32_t i_for
= 0; i_for
< p_sys
->s_allocated
.i_pieces_nbr
; i_for
++)
601 if ( p_sys
->ps_pieces
[i_for
].i_group_ID
== i_group_ID
)
602 p_sys
->ps_pieces
[i_for
].i_group_ID
= p_sys
->ps_pieces
[i_piece_A
].i_group_ID
;
607 if ( abs( ps_piece_A
->i_OTy
- ps_piece_B
->i_OTy
) < 3 )
609 if ( abs( ps_piece_A
->i_ORx
- ps_piece_B
->i_OLx
+ 1 ) < 3
610 && abs( ps_piece_A
->i_TRx
- ps_piece_B
->i_TLx
+ 1 ) < p_sys
->i_magnet_accuracy
611 && abs( ps_piece_A
->i_TRy
- ps_piece_B
->i_TLy
) < p_sys
->i_magnet_accuracy
612 && abs( ps_piece_A
->i_BRx
- ps_piece_B
->i_BLx
+ 1 ) < p_sys
->i_magnet_accuracy
613 && abs( ps_piece_A
->i_BRy
- ps_piece_B
->i_BLy
) < p_sys
->i_magnet_accuracy
)
615 ps_piece_B
->i_left_shape
= 0;
616 ps_piece_A
->i_right_shape
= 6;
619 else if ( abs( ps_piece_A
->i_OLx
- ps_piece_B
->i_OLx
)<3 )
621 if ( abs( ps_piece_A
->i_OBy
- ps_piece_B
->i_OTy
+ 1 )<3
622 && abs( ps_piece_B
->i_TLx
- ps_piece_A
->i_BLx
) < p_sys
->i_magnet_accuracy
623 && abs( ps_piece_B
->i_TLy
- 1 - ps_piece_A
->i_BLy
) < p_sys
->i_magnet_accuracy
624 && abs( ps_piece_B
->i_TRx
- ps_piece_A
->i_BRx
) < p_sys
->i_magnet_accuracy
625 && abs( ps_piece_B
->i_TRy
- 1 - ps_piece_A
->i_BRy
) < p_sys
->i_magnet_accuracy
)
627 ps_piece_B
->i_top_shape
= 2;
628 ps_piece_A
->i_btm_shape
= 4;
634 /*****************************************************************************
635 * puzzle_solve_pces_accuracy: check if pieces are close to their final location
636 * and then adjust position accordingly
637 *****************************************************************************/
638 void puzzle_solve_pces_accuracy( filter_t
*p_filter
) {
639 filter_sys_t
*p_sys
= p_filter
->p_sys
;
641 p_sys
->i_solve_acc_loop
++;
642 if (p_sys
->i_solve_acc_loop
>= p_sys
->s_allocated
.i_pieces_nbr
) {
643 p_sys
->i_done_count
= p_sys
->i_tmp_done_count
;
644 p_sys
->i_tmp_done_count
= 0;
645 p_sys
->i_solve_acc_loop
= 0;
646 p_sys
->b_finished
= (p_sys
->i_done_count
== p_sys
->s_allocated
.i_pieces_nbr
);
649 piece_t
*ps_piece
= &p_sys
->ps_pieces
[p_sys
->i_solve_acc_loop
];
651 ps_piece
->b_finished
= false;
652 if ( ps_piece
->i_actual_mirror
== 1
653 && abs( ps_piece
->i_TRx
- ps_piece
->i_ORx
) < p_sys
->i_magnet_accuracy
654 && abs( ps_piece
->i_TRy
- ps_piece
->i_OTy
) < p_sys
->i_magnet_accuracy
655 && abs( ps_piece
->i_TLx
- ps_piece
->i_OLx
) < p_sys
->i_magnet_accuracy
656 && abs( ps_piece
->i_TLy
- ps_piece
->i_OTy
) < p_sys
->i_magnet_accuracy
)
658 uint32_t i_group_ID
= ps_piece
->i_group_ID
;
659 p_sys
->i_tmp_done_count
++;
661 for ( uint32_t i
= 0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++) {
662 ps_piece
= &p_sys
->ps_pieces
[i
];
663 if ( ( ps_piece
->i_group_ID
== i_group_ID
) && ( !ps_piece
->b_finished
) ) {
664 ps_piece
->ps_piece_in_plane
[0].i_actual_x
= ps_piece
->i_OLx
;
665 ps_piece
->ps_piece_in_plane
[0].i_actual_y
= ps_piece
->i_OTy
;
666 ps_piece
->i_actual_mirror
= +1;
667 puzzle_calculate_corners( p_filter
, i
);
668 ps_piece
->b_finished
= true;
674 /*****************************************************************************
675 * puzzle_sort_layers: sort pieces in order to see in foreground the
676 * standalone ones and those are at the wrong place
677 *****************************************************************************/
678 int puzzle_sort_layers( filter_t
*p_filter
)
680 filter_sys_t
*p_sys
= p_filter
->p_sys
;
683 for (uint32_t i_qty
= 1; i_qty
<= p_sys
->s_current_param
.i_pieces_nbr
; i_qty
++) {
684 /* pieces at the wrong place are in foreground */
685 for (uint32_t i_pce_loop
= 0; i_pce_loop
< p_sys
->s_current_param
.i_pieces_nbr
; i_pce_loop
++) {
686 uint32_t i_grp
= p_sys
->ps_pieces
[i_pce_loop
].i_group_ID
;
687 if ( p_sys
->pi_group_qty
[i_grp
] == (int32_t)i_qty
) {
688 bool b_check_ok
= true;
689 for (int32_t i_pce_check
= 0; i_pce_check
< i_idx
; i_pce_check
++)
690 if ( p_sys
->ps_pieces_tmp
[i_pce_check
].i_group_ID
== i_grp
)
693 for (uint32_t i_pce
= i_pce_loop
; i_pce
< p_sys
->s_current_param
.i_pieces_nbr
; i_pce
++)
694 if (( p_sys
->ps_pieces
[i_pce
].i_group_ID
== i_grp
) && !p_sys
->ps_pieces
[i_pce
].b_finished
) {
695 memcpy( &p_sys
->ps_pieces_tmp
[i_idx
], &p_sys
->ps_pieces
[i_pce
], sizeof(piece_t
));
700 /* pieces at the final location are in background */
701 for (uint32_t i_pce_loop
= 0; i_pce_loop
< p_sys
->s_current_param
.i_pieces_nbr
; i_pce_loop
++) {
702 uint32_t i_grp
= p_sys
->ps_pieces
[i_pce_loop
].i_group_ID
;
703 if ( p_sys
->pi_group_qty
[i_grp
] == (int32_t)i_qty
) {
704 bool b_check_ok
= true;
705 for (int32_t i_pce_check
= 0; i_pce_check
< i_idx
; i_pce_check
++)
706 if ( p_sys
->ps_pieces_tmp
[i_pce_check
].i_group_ID
== i_grp
&& p_sys
->ps_pieces_tmp
[i_pce_check
].b_finished
)
709 for (uint32_t i_pce
= i_pce_loop
; i_pce
< p_sys
->s_current_param
.i_pieces_nbr
; i_pce
++)
710 if (( p_sys
->ps_pieces
[i_pce
].i_group_ID
== i_grp
) && p_sys
->ps_pieces
[i_pce
].b_finished
) {
711 memcpy( &p_sys
->ps_pieces_tmp
[i_idx
], &p_sys
->ps_pieces
[i_pce
], sizeof(piece_t
));
718 free( p_filter
->p_sys
->ps_pieces
);
719 p_filter
->p_sys
->ps_pieces
= p_sys
->ps_pieces_tmp
;
720 p_sys
->ps_pieces_tmp
= malloc( sizeof( piece_t
) * p_sys
->s_allocated
.i_pieces_nbr
);
721 if (!p_sys
->ps_pieces_tmp
)
727 /*****************************************************************************
728 * puzzle_auto_solve: solve the puzzle depending on auto_solve_speed parameter
729 * = move one piece at the final location each time
730 * auto_solve_countdown is < 0
731 *****************************************************************************/
732 void puzzle_auto_solve( filter_t
*p_filter
)
734 filter_sys_t
*p_sys
= p_filter
->p_sys
;
736 if ( p_sys
->s_current_param
.i_auto_solve_speed
< 500 )
739 if ( --p_sys
->i_auto_solve_countdown_val
> 0 )
742 /* delay reached, preset next delay and proceed with puzzle_auto_solve */
743 p_sys
->i_auto_solve_countdown_val
= init_countdown(p_sys
->s_current_param
.i_auto_solve_speed
);
745 /* random piece to be moved */
746 int32_t i_start
= ((unsigned)vlc_mrand48()) % p_sys
->s_allocated
.i_pieces_nbr
;
748 /* here the computer will help player by placing the piece at the final location */
749 for (uint32_t i_l
= 0; i_l
< p_sys
->s_allocated
.i_pieces_nbr
; i_l
++) {
750 int32_t i
= ( i_l
+ i_start
) % p_sys
->s_allocated
.i_pieces_nbr
;
751 if ( !p_sys
->ps_pieces
[i
].b_finished
) {
752 for (uint32_t j
= 0; j
< p_sys
->s_allocated
.i_pieces_nbr
; j
++) {
753 if ( p_sys
->ps_pieces
[j
].i_group_ID
== p_sys
->ps_pieces
[i
].i_group_ID
) {
754 p_sys
->ps_pieces
[j
].i_actual_angle
= 0;
755 p_sys
->ps_pieces
[j
].i_actual_mirror
= +1;
756 p_sys
->ps_pieces
[j
].ps_piece_in_plane
[0].i_actual_x
= p_sys
->ps_pieces
[j
].ps_piece_in_plane
[0].i_original_x
;
757 p_sys
->ps_pieces
[j
].ps_piece_in_plane
[0].i_actual_y
= p_sys
->ps_pieces
[j
].ps_piece_in_plane
[0].i_original_y
;
758 puzzle_calculate_corners( p_filter
, j
);
766 /*****************************************************************************
767 * puzzle_auto_shuffle: shuffle the pieces on the desk depending on
768 * auto_shuffle_speed parameter
769 * = random move of one piece each time
770 * auto_shuffle_countdown is < 0
771 *****************************************************************************/
772 void puzzle_auto_shuffle( filter_t
*p_filter
)
774 filter_sys_t
*p_sys
= p_filter
->p_sys
;
776 if ( p_sys
->s_current_param
.i_auto_shuffle_speed
< 500 )
779 if ( --p_sys
->i_auto_shuffle_countdown_val
> 0 )
782 /* delay reached, preset next delay and proceed with puzzle_auto_shuffle */
783 p_sys
->i_auto_shuffle_countdown_val
= init_countdown(p_sys
->s_current_param
.i_auto_shuffle_speed
);
785 /* random piece to be moved */
786 int32_t i_start
= ((unsigned)vlc_mrand48()) % p_sys
->s_allocated
.i_pieces_nbr
;
788 for (uint32_t i_l
= 0; i_l
< p_sys
->s_allocated
.i_pieces_nbr
; i_l
++){
789 int32_t i
= ( i_l
+ i_start
) % p_sys
->s_allocated
.i_pieces_nbr
;
791 /* find one piece which is part of one group */
792 if ( p_sys
->pi_group_qty
[p_sys
->ps_pieces
[i
].i_group_ID
] > 1 ) {
793 /* find an empty group to be used by this dismantled piece */
794 uint32_t i_new_group
;
795 for ( i_new_group
= 0 ; i_new_group
< p_sys
->s_allocated
.i_pieces_nbr
; i_new_group
++ )
796 if ( p_sys
->pi_group_qty
[i_new_group
] == 0 )
798 p_sys
->ps_pieces
[i
].i_group_ID
= i_new_group
;
799 p_sys
->ps_pieces
[i
].b_finished
= false;
801 /* random rotate & mirror */
802 switch ( p_sys
->s_current_param
.i_rotate
)
805 puzzle_rotate_pce( p_filter
, i
, (( (unsigned) vlc_mrand48()) % ( 2 ) ) * 2, p_sys
->ps_pieces
[i
].i_center_x
, p_sys
->ps_pieces
[i
].i_center_y
, false );
808 puzzle_rotate_pce( p_filter
, i
, (( (unsigned) vlc_mrand48()) % ( 4 ) ), p_sys
->ps_pieces
[i
].i_center_x
, p_sys
->ps_pieces
[i
].i_center_y
, false );
811 puzzle_rotate_pce( p_filter
, i
, (( (unsigned) vlc_mrand48()) % ( 8 ) ), p_sys
->ps_pieces
[i
].i_center_x
, p_sys
->ps_pieces
[i
].i_center_y
, false );
816 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_actual_x
=
817 p_sys
->ps_desk_planes
[0].i_border_width
818 + ( (unsigned) vlc_mrand48()) % ( p_sys
->ps_desk_planes
[0].i_width
- 2*p_sys
->ps_desk_planes
[0].i_border_width
- p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_width
)
819 + p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_width
/ 2 * ( 1 - p_sys
->ps_pieces
[i
].i_step_x_x
)
820 - (p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_lines
/ 2) * p_sys
->ps_pieces
[i
].i_step_y_x
;
821 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_actual_y
=
822 p_sys
->ps_desk_planes
[0].i_border_lines
823 + ( (unsigned) vlc_mrand48()) % ( p_sys
->ps_desk_planes
[0].i_lines
- 2*p_sys
->ps_desk_planes
[0].i_border_lines
- p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_lines
)
824 + p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_lines
/ 2 * ( 1 - p_sys
->ps_pieces
[i
].i_step_y_y
)
825 - (p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_width
/ 2) * p_sys
->ps_pieces
[i
].i_step_x_y
;
827 /* redefine shapes */
828 uint32_t i_left_pce
= 0;
829 uint32_t i_right_pce
= 6;
830 uint32_t i_top_pce
= 2;
831 uint32_t i_btm_pce
= 4;
834 for (int32_t i_row
= 0; i_row
< p_sys
->s_allocated
.i_rows
; i_row
++)
835 for (int32_t i_col
= 0; i_col
< p_sys
->s_allocated
.i_cols
; i_col
++) {
836 if (p_sys
->ps_pieces
[i
].i_original_row
== p_sys
->ps_pieces
[i_pce
].i_original_row
) {
837 if (p_sys
->ps_pieces
[i
].i_original_col
== p_sys
->ps_pieces
[i_pce
].i_original_col
- 1)
839 else if (p_sys
->ps_pieces
[i
].i_original_col
== p_sys
->ps_pieces
[i_pce
].i_original_col
+ 1)
842 else if (p_sys
->ps_pieces
[i
].i_original_col
== p_sys
->ps_pieces
[i_pce
].i_original_col
) {
843 if (p_sys
->ps_pieces
[i
].i_original_row
== p_sys
->ps_pieces
[i_pce
].i_original_row
- 1)
845 else if (p_sys
->ps_pieces
[i
].i_original_row
== p_sys
->ps_pieces
[i_pce
].i_original_row
+ 1)
851 if ((p_sys
->ps_pieces
[i
].i_left_shape
== 0) && (p_sys
->ps_pieces
[i
].i_original_col
!= 0)) {
852 p_sys
->ps_pieces
[i_left_pce
].i_right_shape
= 6 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
853 p_sys
->ps_pieces
[i
].i_left_shape
= (p_sys
->ps_pieces
[i_left_pce
].i_right_shape
- 6 ) ^ 0x01;
856 if ((p_sys
->ps_pieces
[i
].i_right_shape
== 6) && (p_sys
->ps_pieces
[i
].i_original_col
!= p_sys
->s_allocated
.i_cols
-1)) {
857 p_sys
->ps_pieces
[i
].i_right_shape
= 6 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
858 p_sys
->ps_pieces
[i_right_pce
].i_left_shape
= (p_sys
->ps_pieces
[i
].i_right_shape
- 6 ) ^ 0x01;
861 if ((p_sys
->ps_pieces
[i
].i_top_shape
== 2) && (p_sys
->ps_pieces
[i
].i_original_row
!= 0)) {
862 p_sys
->ps_pieces
[i_top_pce
].i_btm_shape
= 4 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
863 p_sys
->ps_pieces
[i
].i_top_shape
= (p_sys
->ps_pieces
[i_top_pce
].i_btm_shape
- 2 ) ^ 0x01;
866 if ((p_sys
->ps_pieces
[i
].i_btm_shape
== 4) && (p_sys
->ps_pieces
[i
].i_original_row
!= p_sys
->s_allocated
.i_rows
-1)) {
867 p_sys
->ps_pieces
[i
].i_btm_shape
= 4 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
868 p_sys
->ps_pieces
[i_btm_pce
].i_top_shape
= (p_sys
->ps_pieces
[i
].i_btm_shape
- 2 ) ^ 0x01;
871 puzzle_calculate_corners( p_filter
, i
);
877 /*****************************************************************************
878 * puzzle_save: save pieces location in memory
879 *****************************************************************************/
880 save_game_t
* puzzle_save(filter_t
*p_filter
)
882 filter_sys_t
*p_sys
= p_filter
->p_sys
;
884 save_game_t
*ps_save_game
= calloc(1, sizeof(*ps_save_game
));
888 ps_save_game
->i_cols
= p_sys
->s_allocated
.i_cols
;
889 ps_save_game
->i_rows
= p_sys
->s_allocated
.i_rows
;
890 ps_save_game
->i_rotate
= p_sys
->s_allocated
.i_rotate
;
892 ps_save_game
->ps_pieces
= calloc( ps_save_game
->i_cols
* ps_save_game
->i_rows
, sizeof(*ps_save_game
->ps_pieces
));
893 if (!ps_save_game
->ps_pieces
) {
898 int32_t i_border_width
= p_sys
->ps_desk_planes
[0].i_border_width
;
899 int32_t i_border_lines
= p_sys
->ps_desk_planes
[0].i_border_lines
;
901 for (int32_t i_pce
= 0; i_pce
< ps_save_game
->i_cols
* ps_save_game
->i_rows
; i_pce
++) {
902 ps_save_game
->ps_pieces
[i_pce
].i_original_row
= p_sys
->ps_pieces
[i_pce
].i_original_row
;
903 ps_save_game
->ps_pieces
[i_pce
].i_original_col
= p_sys
->ps_pieces
[i_pce
].i_original_col
;
904 ps_save_game
->ps_pieces
[i_pce
].i_top_shape
= p_sys
->ps_pieces
[i_pce
].i_top_shape
;
905 ps_save_game
->ps_pieces
[i_pce
].i_btm_shape
= p_sys
->ps_pieces
[i_pce
].i_btm_shape
;
906 ps_save_game
->ps_pieces
[i_pce
].i_right_shape
= p_sys
->ps_pieces
[i_pce
].i_right_shape
;
907 ps_save_game
->ps_pieces
[i_pce
].i_left_shape
= p_sys
->ps_pieces
[i_pce
].i_left_shape
;
908 ps_save_game
->ps_pieces
[i_pce
].f_pos_x
=(p_sys
->ps_pieces
[i_pce
].ps_piece_in_plane
[0].i_actual_x
- i_border_width
) / ((float)p_sys
->ps_desk_planes
[0].i_width
- 2*i_border_width
);
909 ps_save_game
->ps_pieces
[i_pce
].f_pos_y
=(p_sys
->ps_pieces
[i_pce
].ps_piece_in_plane
[0].i_actual_y
- i_border_lines
) / ((float)p_sys
->ps_desk_planes
[0].i_lines
- 2*i_border_lines
);
910 ps_save_game
->ps_pieces
[i_pce
].i_actual_angle
= p_sys
->ps_pieces
[i_pce
].i_actual_angle
;
911 ps_save_game
->ps_pieces
[i_pce
].i_actual_mirror
= p_sys
->ps_pieces
[i_pce
].i_actual_mirror
;
917 void puzzle_load( filter_t
*p_filter
, save_game_t
*ps_save_game
)
919 filter_sys_t
*p_sys
= p_filter
->p_sys
;
921 if (p_sys
->s_current_param
.i_cols
!= ps_save_game
->i_cols
922 || p_sys
->s_allocated
.i_rows
!= ps_save_game
->i_rows
923 || p_sys
->s_allocated
.i_rotate
!= ps_save_game
->i_rotate
)
926 int32_t i_border_width
= p_sys
->ps_desk_planes
[0].i_border_width
;
927 int32_t i_border_lines
= p_sys
->ps_desk_planes
[0].i_border_lines
;
929 for (uint32_t i_pce
=0; i_pce
< p_sys
->s_allocated
.i_pieces_nbr
; i_pce
++) {
930 for (uint32_t i
=0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++)
931 if ( p_sys
->ps_pieces
[i
].i_original_row
== ps_save_game
->ps_pieces
[i_pce
].i_original_row
932 && p_sys
->ps_pieces
[i
].i_original_col
== ps_save_game
->ps_pieces
[i_pce
].i_original_col
)
934 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_actual_x
= i_border_width
935 + ((float)p_sys
->ps_desk_planes
[0].i_width
- 2 * i_border_width
)
936 * ps_save_game
->ps_pieces
[i_pce
].f_pos_x
;
937 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_actual_y
= i_border_lines
938 + ((float)p_sys
->ps_desk_planes
[0].i_lines
- 2 * i_border_lines
)
939 * ps_save_game
->ps_pieces
[i_pce
].f_pos_y
;
941 p_sys
->ps_pieces
[i
].i_top_shape
= ps_save_game
->ps_pieces
[i_pce
].i_top_shape
;
942 p_sys
->ps_pieces
[i
].i_btm_shape
= ps_save_game
->ps_pieces
[i_pce
].i_btm_shape
;
943 p_sys
->ps_pieces
[i
].i_right_shape
= ps_save_game
->ps_pieces
[i_pce
].i_right_shape
;
944 p_sys
->ps_pieces
[i
].i_left_shape
= ps_save_game
->ps_pieces
[i_pce
].i_left_shape
;
945 p_sys
->ps_pieces
[i
].i_actual_angle
= ps_save_game
->ps_pieces
[i_pce
].i_actual_angle
;
946 p_sys
->ps_pieces
[i
].i_actual_mirror
= ps_save_game
->ps_pieces
[i_pce
].i_actual_mirror
;
947 p_sys
->ps_pieces
[i
].i_group_ID
= i_pce
;
948 p_sys
->ps_pieces
[i
].b_finished
= false;
950 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_actual_x
= i_border_width
+ ((float)p_sys
->ps_desk_planes
[0].i_width
951 - 2*i_border_width
) * ps_save_game
->ps_pieces
[i_pce
].f_pos_x
;
952 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_actual_y
= i_border_lines
+ ((float)p_sys
->ps_desk_planes
[0].i_lines
953 - 2*i_border_lines
) * ps_save_game
->ps_pieces
[i_pce
].f_pos_y
;
954 puzzle_calculate_corners( p_filter
, i
);
960 for (uint32_t i_pce
=0; i_pce
< p_sys
->s_allocated
.i_pieces_nbr
; i_pce
++) {
961 /* redefine shapes */
962 uint32_t i_left_pce
= 0;
963 uint32_t i_right_pce
= 6;
964 uint32_t i_top_pce
= 2;
965 uint32_t i_btm_pce
= 4;
967 uint32_t i_pce_pair
= 0;
968 for (int32_t i_row
= 0; i_row
< p_sys
->s_allocated
.i_rows
; i_row
++)
969 for (int32_t i_col
= 0; i_col
< p_sys
->s_allocated
.i_cols
; i_col
++) {
970 if (p_sys
->ps_pieces
[i_pce
].i_original_row
== p_sys
->ps_pieces
[i_pce_pair
].i_original_row
) {
971 if (p_sys
->ps_pieces
[i_pce
].i_original_col
== p_sys
->ps_pieces
[i_pce_pair
].i_original_col
- 1)
972 i_right_pce
= i_pce_pair
;
973 else if (p_sys
->ps_pieces
[i_pce
].i_original_col
== p_sys
->ps_pieces
[i_pce_pair
].i_original_col
+ 1)
974 i_left_pce
= i_pce_pair
;
976 else if (p_sys
->ps_pieces
[i_pce
].i_original_col
== p_sys
->ps_pieces
[i_pce_pair
].i_original_col
) {
977 if (p_sys
->ps_pieces
[i_pce
].i_original_row
== p_sys
->ps_pieces
[i_pce_pair
].i_original_row
- 1)
978 i_btm_pce
= i_pce_pair
;
979 else if (p_sys
->ps_pieces
[i_pce
].i_original_row
== p_sys
->ps_pieces
[i_pce_pair
].i_original_row
+ 1)
980 i_top_pce
= i_pce_pair
;
985 if ((p_sys
->ps_pieces
[i_pce
].i_left_shape
== 0) && (p_sys
->ps_pieces
[i_pce
].i_original_col
!= 0)) {
986 p_sys
->ps_pieces
[i_left_pce
].i_right_shape
= 6 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
987 p_sys
->ps_pieces
[i_pce
].i_left_shape
= (p_sys
->ps_pieces
[i_left_pce
].i_right_shape
- 6 ) ^ 0x01;
990 if ((p_sys
->ps_pieces
[i_pce
].i_right_shape
== 6) && (p_sys
->ps_pieces
[i_pce
].i_original_col
!= p_sys
->s_allocated
.i_cols
-1)) {
991 p_sys
->ps_pieces
[i_pce
].i_right_shape
= 6 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
992 p_sys
->ps_pieces
[i_right_pce
].i_left_shape
= (p_sys
->ps_pieces
[i_pce
].i_right_shape
- 6 ) ^ 0x01;
995 if ((p_sys
->ps_pieces
[i_pce
].i_top_shape
== 2) && (p_sys
->ps_pieces
[i_pce
].i_original_row
!= 0)) {
996 p_sys
->ps_pieces
[i_top_pce
].i_btm_shape
= 4 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
997 p_sys
->ps_pieces
[i_pce
].i_top_shape
= (p_sys
->ps_pieces
[i_top_pce
].i_btm_shape
- 2 ) ^ 0x01;
1000 if ((p_sys
->ps_pieces
[i_pce
].i_btm_shape
== 4) && (p_sys
->ps_pieces
[i_pce
].i_original_row
!= p_sys
->s_allocated
.i_rows
-1)) {
1001 p_sys
->ps_pieces
[i_pce
].i_btm_shape
= 4 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
1002 p_sys
->ps_pieces
[i_btm_pce
].i_top_shape
= (p_sys
->ps_pieces
[i_pce
].i_btm_shape
- 2 ) ^ 0x01;