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>
40 #include "filter_picture.h"
42 #include "puzzle_bezier.h"
43 #include "puzzle_lib.h"
44 #include "puzzle_pce.h"
45 #include "puzzle_mgt.h"
47 /*****************************************************************************
48 * puzzle_bake: compute general puzzle data and allocate structures
49 *****************************************************************************/
50 int puzzle_bake( filter_t
*p_filter
, picture_t
*p_pic_out
, picture_t
*p_pic_in
)
52 filter_sys_t
*p_sys
= p_filter
->p_sys
;
55 puzzle_free_ps_puzzle_array ( p_filter
);
56 puzzle_free_ps_pieces_shapes ( p_filter
);
57 puzzle_free_ps_pieces ( p_filter
);
59 p_sys
->s_allocated
.i_rows
= p_sys
->s_current_param
.i_rows
;
60 p_sys
->s_allocated
.i_cols
= p_sys
->s_current_param
.i_cols
;
61 p_sys
->s_allocated
.i_planes
= p_sys
->s_current_param
.i_planes
;
62 p_sys
->s_allocated
.i_piece_types
= ((p_sys
->s_current_param
.b_advanced
)?PIECE_TYPE_NBR
:0);
63 p_sys
->s_allocated
.i_pieces_nbr
= p_sys
->s_allocated
.i_rows
* p_sys
->s_allocated
.i_cols
;
64 p_sys
->s_allocated
.b_preview
= p_sys
->s_current_param
.b_preview
;
65 p_sys
->s_allocated
.i_preview_size
= p_sys
->s_current_param
.i_preview_size
;
66 p_sys
->s_allocated
.i_border
= p_sys
->s_current_param
.i_border
;
67 p_sys
->s_allocated
.b_blackslot
= p_sys
->s_current_param
.b_blackslot
;
68 p_sys
->s_allocated
.b_near
= p_sys
->s_current_param
.b_near
;
69 p_sys
->s_allocated
.i_shape_size
= p_sys
->s_current_param
.i_shape_size
;
70 p_sys
->s_allocated
.b_advanced
= p_sys
->s_current_param
.b_advanced
;
71 p_sys
->s_allocated
.i_auto_shuffle_speed
= p_sys
->s_current_param
.i_auto_shuffle_speed
;
72 p_sys
->s_allocated
.i_auto_solve_speed
= p_sys
->s_current_param
.i_auto_solve_speed
;
73 p_sys
->s_allocated
.i_rotate
= p_sys
->s_current_param
.i_rotate
;
75 p_sys
->ps_puzzle_array
= malloc( sizeof( puzzle_array_t
** ) * (p_sys
->s_allocated
.i_rows
+ 1));
76 if( !p_sys
->ps_puzzle_array
)
79 for (int32_t r
=0; r
< p_sys
->s_allocated
.i_rows
+ 1; r
++) {
80 p_sys
->ps_puzzle_array
[r
] = malloc( sizeof( puzzle_array_t
* ) * (p_sys
->s_allocated
.i_cols
+ 1));
81 if( !p_sys
->ps_puzzle_array
[r
] )
83 for (int32_t c
=0; c
< p_sys
->s_allocated
.i_cols
+ 1; c
++) {
84 p_sys
->ps_puzzle_array
[r
][c
] = malloc( sizeof( puzzle_array_t
) * p_sys
->s_allocated
.i_planes
);
85 if( !p_sys
->ps_puzzle_array
[r
][c
] )
90 p_sys
->ps_desk_planes
= malloc( sizeof( puzzle_plane_t
) * p_sys
->s_allocated
.i_planes
);
91 if( !p_sys
->ps_desk_planes
)
93 p_sys
->ps_pict_planes
= malloc( sizeof( puzzle_plane_t
) * p_sys
->s_allocated
.i_planes
);
94 if( !p_sys
->ps_pict_planes
)
97 for (uint8_t i_plane
= 0; i_plane
< p_sys
->s_allocated
.i_planes
; i_plane
++) {
98 p_sys
->ps_desk_planes
[i_plane
].i_lines
= p_pic_out
->p
[i_plane
].i_visible_lines
;
99 p_sys
->ps_desk_planes
[i_plane
].i_pitch
= p_pic_out
->p
[i_plane
].i_pitch
;
100 p_sys
->ps_desk_planes
[i_plane
].i_visible_pitch
= p_pic_out
->p
[i_plane
].i_visible_pitch
;
101 p_sys
->ps_desk_planes
[i_plane
].i_pixel_pitch
= p_pic_out
->p
[i_plane
].i_pixel_pitch
;
102 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
;
104 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;
105 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;
107 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;
108 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;
110 p_sys
->ps_desk_planes
[i_plane
].i_pce_max_width
= (( p_sys
->ps_desk_planes
[i_plane
].i_width
111 - 2 * p_sys
->ps_desk_planes
[i_plane
].i_border_width
) + p_sys
->s_allocated
.i_cols
- 1 ) / p_sys
->s_allocated
.i_cols
;
112 p_sys
->ps_desk_planes
[i_plane
].i_pce_max_lines
= (( p_sys
->ps_desk_planes
[i_plane
].i_lines
113 - 2 * p_sys
->ps_desk_planes
[i_plane
].i_border_lines
) + p_sys
->s_allocated
.i_rows
- 1 ) / p_sys
->s_allocated
.i_rows
;
115 p_sys
->ps_pict_planes
[i_plane
].i_lines
= p_pic_in
->p
[i_plane
].i_visible_lines
;
116 p_sys
->ps_pict_planes
[i_plane
].i_pitch
= p_pic_in
->p
[i_plane
].i_pitch
;
117 p_sys
->ps_pict_planes
[i_plane
].i_visible_pitch
= p_pic_in
->p
[i_plane
].i_visible_pitch
;
118 p_sys
->ps_pict_planes
[i_plane
].i_pixel_pitch
= p_pic_in
->p
[i_plane
].i_pixel_pitch
;
119 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
;
121 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;
122 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;
124 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;
125 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;
127 p_sys
->ps_pict_planes
[i_plane
].i_pce_max_width
= (( p_sys
->ps_desk_planes
[i_plane
].i_width
128 - 2 * p_sys
->ps_pict_planes
[i_plane
].i_border_width
) + p_sys
->s_allocated
.i_cols
- 1 ) / p_sys
->s_allocated
.i_cols
;
129 p_sys
->ps_pict_planes
[i_plane
].i_pce_max_lines
= (( p_sys
->ps_pict_planes
[i_plane
].i_lines
130 - 2 * p_sys
->ps_pict_planes
[i_plane
].i_border_lines
) + p_sys
->s_allocated
.i_rows
- 1 ) / p_sys
->s_allocated
.i_rows
;
132 for (int32_t r
= 0; r
< p_sys
->s_allocated
.i_rows
; r
++)
133 for (int32_t c
= 0; c
< p_sys
->s_allocated
.i_cols
; c
++) {
135 p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_y
= p_sys
->ps_pict_planes
[i_plane
].i_border_lines
;
137 p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_x
= p_sys
->ps_pict_planes
[i_plane
].i_border_width
;
138 p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_width
=
139 (p_sys
->ps_pict_planes
[i_plane
].i_width
- p_sys
->ps_pict_planes
[i_plane
].i_border_width
140 - p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_x
) / ( p_sys
->s_allocated
.i_cols
- c
);
141 p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_lines
=
142 (p_sys
->ps_pict_planes
[i_plane
].i_lines
- p_sys
->ps_pict_planes
[i_plane
].i_border_lines
143 - p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_y
) / ( p_sys
->s_allocated
.i_rows
- r
);
144 p_sys
->ps_puzzle_array
[r
][c
+ 1][i_plane
].i_x
=
145 p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_x
+ p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_width
;
146 p_sys
->ps_puzzle_array
[r
+ 1][c
][i_plane
].i_y
=
147 p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_y
+ p_sys
->ps_puzzle_array
[r
][c
][i_plane
].i_lines
;
151 p_sys
->i_magnet_accuracy
= ( p_sys
->s_current_param
.i_pict_width
/ 50) + 3;
153 if (p_sys
->s_current_param
.b_advanced
&& p_sys
->s_allocated
.i_shape_size
!= 0) {
154 i_ret
= puzzle_bake_pieces_shapes ( p_filter
);
155 if (i_ret
!= VLC_SUCCESS
)
159 i_ret
= puzzle_bake_piece ( p_filter
);
160 if (i_ret
!= VLC_SUCCESS
)
163 if ( (p_sys
->pi_order
!= NULL
) && (p_sys
->ps_desk_planes
!= NULL
) && (p_sys
->ps_pict_planes
!= NULL
)
164 && (p_sys
->ps_puzzle_array
!= NULL
) && (p_sys
->ps_pieces
!= NULL
) )
165 p_sys
->b_init
= true;
167 if ( (p_sys
->ps_pieces_shapes
== NULL
) && (p_sys
->s_current_param
.b_advanced
)
168 && (p_sys
->s_current_param
.i_shape_size
!= 0) )
169 p_sys
->b_init
= false;
174 void puzzle_free_ps_puzzle_array( filter_t
*p_filter
)
176 filter_sys_t
*p_sys
= p_filter
->p_sys
;
178 if (p_sys
->ps_puzzle_array
!= NULL
) {
179 for (int32_t r
=0; r
< p_sys
->s_allocated
.i_rows
+ 1; r
++) {
180 for (int32_t c
=0; c
< p_sys
->s_allocated
.i_cols
+ 1; c
++)
181 free( p_sys
->ps_puzzle_array
[r
][c
] );
182 free( p_sys
->ps_puzzle_array
[r
] );
184 free( p_sys
->ps_puzzle_array
);
186 p_sys
->ps_puzzle_array
= NULL
;
188 free ( p_sys
->ps_desk_planes
);
189 p_sys
->ps_desk_planes
= NULL
;
191 free ( p_sys
->ps_pict_planes
);
192 p_sys
->ps_pict_planes
= NULL
;
197 /*****************************************************************************
198 * puzzle_bake_piece: compute data dedicated to each piece
199 *****************************************************************************/
200 int puzzle_bake_piece( filter_t
*p_filter
)
202 int i_ret
= puzzle_allocate_ps_pieces( p_filter
);
203 if (i_ret
!= VLC_SUCCESS
)
206 filter_sys_t
*p_sys
= p_filter
->p_sys
;
208 /* generates random pi_order array */
209 i_ret
= puzzle_shuffle( p_filter
);
210 if (i_ret
!= VLC_SUCCESS
)
214 for (int32_t row
= 0; row
< p_sys
->s_allocated
.i_rows
; row
++) {
215 for (int32_t col
= 0; col
< p_sys
->s_allocated
.i_cols
; col
++) {
219 if (p_sys
->pi_order
!= NULL
) {
220 orow
= p_sys
->pi_order
[i
] / (p_sys
->s_allocated
.i_cols
);
221 ocol
= p_sys
->pi_order
[i
] % (p_sys
->s_allocated
.i_cols
);
224 p_sys
->ps_pieces
[i
].i_original_row
= orow
;
225 p_sys
->ps_pieces
[i
].i_original_col
= ocol
;
227 /* set bottom and right shapes */
228 p_sys
->ps_pieces
[i
].i_left_shape
= 0;
229 p_sys
->ps_pieces
[i
].i_top_shape
= 2;
230 p_sys
->ps_pieces
[i
].i_btm_shape
= 4;
231 p_sys
->ps_pieces
[i
].i_right_shape
= 6;
233 if (p_sys
->s_allocated
.i_shape_size
> 0) {
235 if (orow
< p_sys
->s_allocated
.i_rows
- 1)
236 p_sys
->ps_pieces
[i
].i_btm_shape
= 4 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
238 if (ocol
< p_sys
->s_allocated
.i_cols
- 1)
239 p_sys
->ps_pieces
[i
].i_right_shape
= 6 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
243 p_sys
->ps_pieces
[i
].i_actual_angle
= 0;
244 p_sys
->ps_pieces
[i
].b_overlap
= false;
245 p_sys
->ps_pieces
[i
].i_actual_mirror
= +1;
246 p_sys
->ps_pieces
[i
].b_finished
= ((ocol
== col
) && (orow
== row
));
247 p_sys
->ps_pieces
[i
].i_group_ID
= i
;
249 /* add small random offset to location */
250 int32_t i_rand_x
= 0;
251 int32_t i_rand_y
= 0;
252 if (p_sys
->s_current_param
.b_advanced
) {
253 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;
254 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;
257 /* copy related puzzle data to piece data */
258 if (p_sys
->ps_puzzle_array
!= NULL
) {
259 for (uint8_t i_plane
= 0; i_plane
< p_sys
->s_allocated
.i_planes
; i_plane
++) {
261 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[i_plane
].i_width
= p_sys
->ps_puzzle_array
[row
][col
][i_plane
].i_width
;
262 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[i_plane
].i_lines
= p_sys
->ps_puzzle_array
[row
][col
][i_plane
].i_lines
;
263 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
;
264 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
;
265 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
*
266 p_sys
->ps_desk_planes
[i_plane
].i_width
/ p_sys
->ps_desk_planes
[0].i_width
;
267 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
*
268 p_sys
->ps_desk_planes
[i_plane
].i_lines
/ p_sys
->ps_desk_planes
[0].i_lines
;
272 p_sys
->ps_pieces
[i
].i_OLx
= p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_original_x
;
273 p_sys
->ps_pieces
[i
].i_OTy
= p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_original_y
;
274 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;
275 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;
277 puzzle_calculate_corners( p_filter
, i
);
285 /* left and top shapes are based on negative right and bottom ones */
286 puzzle_set_left_top_shapes( p_filter
);
288 /* add random rotation to each piece */
289 puzzle_random_rotate( p_filter
);
294 /*****************************************************************************
295 * puzzle_set_left_top_shapes: Set the shape ID to be used for top and left
296 * edges of each piece. Those ID will be set to
297 * be the negative of bottom or right of adjacent
299 *****************************************************************************/
300 void puzzle_set_left_top_shapes( filter_t
*p_filter
)
302 filter_sys_t
*p_sys
= p_filter
->p_sys
;
303 /* for each piece on the desk... */
304 for (uint16_t i_pce_B
=0; i_pce_B
< p_sys
->s_allocated
.i_pieces_nbr
; i_pce_B
++)
305 /* ...search adjacent piece */
306 for (uint16_t i_pce_A
=0; i_pce_A
< p_sys
->s_allocated
.i_pieces_nbr
; i_pce_A
++)
308 if ( ( p_sys
->ps_pieces
[i_pce_A
].i_original_row
== p_sys
->ps_pieces
[i_pce_B
].i_original_row
)
309 && ( p_sys
->ps_pieces
[i_pce_A
].i_original_col
== p_sys
->ps_pieces
[i_pce_B
].i_original_col
-1 ) )
310 /* left shape is based on negative (invert ID LSB) right one */
311 p_sys
->ps_pieces
[i_pce_B
].i_left_shape
= (p_sys
->ps_pieces
[i_pce_A
].i_right_shape
- 6 ) ^ 0x01;
313 if ( ( p_sys
->ps_pieces
[i_pce_A
].i_original_row
== p_sys
->ps_pieces
[i_pce_B
].i_original_row
- 1 )
314 && ( p_sys
->ps_pieces
[i_pce_A
].i_original_col
== p_sys
->ps_pieces
[i_pce_B
].i_original_col
) )
315 /* top shape is based on negative of bottom one
316 * top ID = bottom ID - 2
317 * negative ID = invert LSB
319 p_sys
->ps_pieces
[i_pce_B
].i_top_shape
= (p_sys
->ps_pieces
[i_pce_A
].i_btm_shape
- 2 ) ^ 0x01;
323 void puzzle_random_rotate( filter_t
*p_filter
)
325 filter_sys_t
*p_sys
= p_filter
->p_sys
;
326 /* add random rotation to each piece */
327 for (uint32_t i
= 0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++)
329 p_sys
->ps_pieces
[i
].i_actual_angle
= 0;
330 p_sys
->ps_pieces
[i
].i_actual_mirror
= +1;
332 switch ( p_sys
->s_current_param
.i_rotate
)
335 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 );
338 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 );
341 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 );
344 puzzle_calculate_corners( p_filter
, i
);
348 void puzzle_free_ps_pieces( filter_t
*p_filter
)
350 filter_sys_t
*p_sys
= p_filter
->p_sys
;
352 if (p_sys
->ps_pieces
!= NULL
) {
353 for (uint32_t i_pce
= 0; i_pce
< p_sys
->s_allocated
.i_pieces_nbr
; i_pce
++)
354 free( p_sys
->ps_pieces
[i_pce
].ps_piece_in_plane
);
355 free( p_sys
->ps_pieces
);
357 p_sys
->ps_pieces
= NULL
;
359 free( p_sys
->pi_order
);
360 p_sys
->pi_order
= NULL
;
362 free( p_sys
->ps_pieces_tmp
);
363 p_sys
->ps_pieces_tmp
= NULL
;
365 free( p_sys
->pi_group_qty
);
366 p_sys
->pi_group_qty
= NULL
;
371 int puzzle_allocate_ps_pieces( filter_t
*p_filter
)
373 filter_sys_t
*p_sys
= p_filter
->p_sys
;
374 puzzle_free_ps_pieces(p_filter
);
375 p_sys
->s_allocated
.i_pieces_nbr
= p_sys
->s_allocated
.i_rows
* p_sys
->s_allocated
.i_cols
;
376 p_sys
->ps_pieces
= malloc( sizeof( piece_t
) * p_sys
->s_allocated
.i_pieces_nbr
);
377 if( !p_sys
->ps_pieces
)
379 for (uint32_t p
= 0; p
< p_sys
->s_allocated
.i_pieces_nbr
; p
++) {
380 p_sys
->ps_pieces
[p
].ps_piece_in_plane
= malloc( sizeof( piece_in_plane_t
) * p_sys
->s_allocated
.i_planes
);
381 if( !p_sys
->ps_pieces
[p
].ps_piece_in_plane
) {
382 for (uint32_t i
=0;i
<p
;i
++)
383 free(p_sys
->ps_pieces
[i
].ps_piece_in_plane
);
384 free(p_sys
->ps_pieces
);
385 p_sys
->ps_pieces
= NULL
;
390 p_sys
->ps_pieces_tmp
= malloc( sizeof( piece_t
) * p_sys
->s_allocated
.i_pieces_nbr
);
391 if( !p_sys
->ps_pieces_tmp
) {
392 for (uint32_t i
=0;i
<p_sys
->s_allocated
.i_pieces_nbr
;i
++)
393 free(p_sys
->ps_pieces
[i
].ps_piece_in_plane
);
394 free(p_sys
->ps_pieces
);
395 p_sys
->ps_pieces
= NULL
;
398 p_sys
->pi_group_qty
= malloc( sizeof( int32_t ) * (p_sys
->s_allocated
.i_pieces_nbr
));
399 if( !p_sys
->pi_group_qty
) {
400 for (uint32_t i
=0;i
<p_sys
->s_allocated
.i_pieces_nbr
;i
++)
401 free(p_sys
->ps_pieces
[i
].ps_piece_in_plane
);
402 free(p_sys
->ps_pieces
);
403 p_sys
->ps_pieces
= NULL
;
404 free(p_sys
->ps_pieces_tmp
);
405 p_sys
->ps_pieces_tmp
= NULL
;
411 bool puzzle_is_valid( filter_sys_t
*p_sys
, int32_t *pi_pce_lst
)
413 const int32_t i_count
= p_sys
->s_allocated
.i_pieces_nbr
;
415 if( !p_sys
->s_current_param
.b_blackslot
)
419 for( int32_t i
= 0; i
< i_count
; i
++ ) {
420 if( pi_pce_lst
[i
] == i_count
- 1 ) {
421 d
+= i
/ p_sys
->s_allocated
.i_cols
+ 1;
424 for( int32_t j
= i
+1; j
< i_count
; j
++ ) {
425 if( pi_pce_lst
[j
] == i_count
- 1 )
427 if( pi_pce_lst
[i
] > pi_pce_lst
[j
] )
434 int puzzle_shuffle( filter_t
*p_filter
)
436 filter_sys_t
*p_sys
= p_filter
->p_sys
;
438 int32_t i_pieces_nbr
= p_sys
->s_allocated
.i_pieces_nbr
;
442 int i_ret
= puzzle_generate_rand_pce_list( p_filter
, &p_sys
->pi_order
);
443 if (i_ret
!= VLC_SUCCESS
)
445 } while( puzzle_is_finished( p_sys
, p_sys
->pi_order
) || !puzzle_is_valid( p_sys
, p_sys
->pi_order
) );
448 if( p_sys
->s_current_param
.b_blackslot
) {
449 for( int32_t i
= 0; i
< i_pieces_nbr
; i
++ )
450 if( p_sys
->pi_order
[i
] == i_pieces_nbr
- 1 ) {
451 p_sys
->i_selected
= i
;
456 p_sys
->i_selected
= NO_PCE
;
459 p_sys
->b_shuffle_rqst
= false;
460 p_sys
->b_finished
= false;
465 int puzzle_generate_rand_pce_list( filter_t
*p_filter
, int32_t **pi_pce_lst
)
467 filter_sys_t
*p_sys
= p_filter
->p_sys
;
469 int32_t i_pieces_nbr
= p_sys
->s_allocated
.i_pieces_nbr
;
471 if (pi_pce_lst
!= NULL
)
473 *pi_pce_lst
= calloc( i_pieces_nbr
, sizeof(**pi_pce_lst
) );
477 for( int32_t i
= 0; i
< i_pieces_nbr
; i
++ )
478 (*pi_pce_lst
)[i
] = NO_PCE
;
480 for( int32_t c
= 0; c
< i_pieces_nbr
; ) {
481 int32_t i
= ((unsigned)vlc_mrand48()) % i_pieces_nbr
;
482 if( (*pi_pce_lst
)[i
] == NO_PCE
)
483 (*pi_pce_lst
)[i
] = c
++;
488 bool puzzle_is_finished( filter_sys_t
*p_sys
, int32_t *pi_pce_lst
)
490 for( uint32_t i
= 0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++ )
491 if( (int32_t)i
!= pi_pce_lst
[i
] )
497 int puzzle_piece_foreground( filter_t
*p_filter
, int32_t i_piece
) {
498 filter_sys_t
*p_sys
= p_filter
->p_sys
;
499 piece_t
*ps_pieces_tmp
; /* list [piece] of pieces data. Sort as per layers */
500 uint32_t i_group_ID
= p_sys
->ps_pieces
[i_piece
].i_group_ID
;
502 ps_pieces_tmp
= malloc( sizeof( piece_t
) * p_sys
->s_allocated
.i_pieces_nbr
);
508 memcpy( &ps_pieces_tmp
[j
], &p_sys
->ps_pieces
[i_piece
], sizeof(piece_t
) );
511 for (uint32_t i
= 0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++) {
512 if ( ( p_sys
->ps_pieces
[i
].i_group_ID
== i_group_ID
) && ( (int32_t)i
!= i_piece
) ) {
513 memcpy( &ps_pieces_tmp
[j
], &p_sys
->ps_pieces
[i
], sizeof(piece_t
));
517 for (uint32_t i
= 0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++) {
518 if ( p_sys
->ps_pieces
[i
].i_group_ID
!= i_group_ID
) {
519 memcpy( &ps_pieces_tmp
[j
], &p_sys
->ps_pieces
[i
], sizeof(piece_t
));
524 free( p_filter
->p_sys
->ps_pieces
);
525 p_filter
->p_sys
->ps_pieces
= ps_pieces_tmp
;
530 void puzzle_count_pce_group( filter_t
*p_filter
) { /* count pce in each group */
531 filter_sys_t
*p_sys
= p_filter
->p_sys
;
533 memset ( p_sys
->pi_group_qty
, 0, sizeof( int32_t ) * (p_sys
->s_allocated
.i_pieces_nbr
) );
534 for (uint32_t i_pce
= 0; i_pce
< p_sys
->s_allocated
.i_pieces_nbr
; i_pce
++)
535 p_sys
->pi_group_qty
[p_sys
->ps_pieces
[i_pce
].i_group_ID
]++;
538 /*****************************************************************************
539 * puzzle_solve_pces_group: check if pieces are close together
540 * and then combine in a group
541 *****************************************************************************/
542 void puzzle_solve_pces_group( filter_t
*p_filter
) {
543 filter_sys_t
*p_sys
= p_filter
->p_sys
;
546 p_sys
->i_solve_grp_loop
++;
547 p_sys
->i_solve_grp_loop
%= p_sys
->s_allocated
.i_pieces_nbr
;
549 int32_t i_piece_A
= p_sys
->i_solve_grp_loop
;
550 piece_t
*ps_piece_A
= &p_sys
->ps_pieces
[i_piece_A
];
552 for (uint32_t i_piece_B
= 0; i_piece_B
< p_sys
->s_allocated
.i_pieces_nbr
; i_piece_B
++)
554 piece_t
*ps_piece_B
= &p_sys
->ps_pieces
[i_piece_B
];
556 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
)
559 if ( (ps_piece_B
->i_group_ID
!= p_sys
->ps_pieces
[i_piece_A
].i_group_ID
) )
561 if ( abs(ps_piece_A
->i_OTy
- ps_piece_B
->i_OTy
)<3)
563 if ( abs( ps_piece_A
->i_ORx
- ps_piece_B
->i_OLx
+ 1 ) < 3
564 && abs( ps_piece_A
->i_TRx
- ps_piece_B
->i_TLx
+ 1 ) < p_sys
->i_magnet_accuracy
565 && abs( ps_piece_A
->i_TRy
- ps_piece_B
->i_TLy
) < p_sys
->i_magnet_accuracy
566 && abs( ps_piece_A
->i_BRx
- ps_piece_B
->i_BLx
+ 1 ) < p_sys
->i_magnet_accuracy
567 && abs( ps_piece_A
->i_BRy
- ps_piece_B
->i_BLy
) < p_sys
->i_magnet_accuracy
)
569 i_dx
= ps_piece_A
->i_TRx
- ps_piece_B
->i_TLx
+ ps_piece_A
->i_step_x_x
;
570 i_dy
= ps_piece_A
->i_TRy
- ps_piece_B
->i_TLy
;
572 if (!ps_piece_B
->b_finished
)
573 puzzle_move_group( p_filter
, i_piece_B
, i_dx
, i_dy
);
575 puzzle_move_group( p_filter
, i_piece_A
, -i_dx
, -i_dy
);
577 uint32_t i_group_ID
= ps_piece_B
->i_group_ID
;
578 for (uint32_t i_for
= 0; i_for
< p_sys
->s_allocated
.i_pieces_nbr
; i_for
++)
579 if ( p_sys
->ps_pieces
[i_for
].i_group_ID
== i_group_ID
)
580 p_sys
->ps_pieces
[i_for
].i_group_ID
= p_sys
->ps_pieces
[i_piece_A
].i_group_ID
;
583 else if ( abs(ps_piece_A
->i_OLx
- ps_piece_B
->i_OLx
) < 3 )
585 if ( abs(ps_piece_A
->i_OBy
- ps_piece_B
->i_OTy
+ 1 ) < 3
586 && abs( ps_piece_B
->i_TLx
- ps_piece_A
->i_BLx
) < p_sys
->i_magnet_accuracy
587 && abs( ps_piece_B
->i_TLy
- 1 - ps_piece_A
->i_BLy
) < p_sys
->i_magnet_accuracy
588 && abs( ps_piece_B
->i_TRx
- ps_piece_A
->i_BRx
) < p_sys
->i_magnet_accuracy
589 && abs( ps_piece_B
->i_TRy
- 1 - ps_piece_A
->i_BRy
) < p_sys
->i_magnet_accuracy
)
592 i_dx
= ps_piece_A
->i_BLx
- ps_piece_B
->i_TLx
;
593 i_dy
= ps_piece_A
->i_BLy
- ps_piece_B
->i_TLy
+ ps_piece_A
->i_step_y_y
;
595 if (!ps_piece_B
->b_finished
)
596 puzzle_move_group( p_filter
, i_piece_B
, i_dx
, i_dy
);
598 puzzle_move_group( p_filter
, i_piece_A
, -i_dx
, -i_dy
);
600 uint32_t i_group_ID
= ps_piece_B
->i_group_ID
;
601 for (uint32_t i_for
= 0; i_for
< p_sys
->s_allocated
.i_pieces_nbr
; i_for
++)
602 if ( p_sys
->ps_pieces
[i_for
].i_group_ID
== i_group_ID
)
603 p_sys
->ps_pieces
[i_for
].i_group_ID
= p_sys
->ps_pieces
[i_piece_A
].i_group_ID
;
608 if ( abs( ps_piece_A
->i_OTy
- ps_piece_B
->i_OTy
) < 3 )
610 if ( abs( ps_piece_A
->i_ORx
- ps_piece_B
->i_OLx
+ 1 ) < 3
611 && abs( ps_piece_A
->i_TRx
- ps_piece_B
->i_TLx
+ 1 ) < p_sys
->i_magnet_accuracy
612 && abs( ps_piece_A
->i_TRy
- ps_piece_B
->i_TLy
) < p_sys
->i_magnet_accuracy
613 && abs( ps_piece_A
->i_BRx
- ps_piece_B
->i_BLx
+ 1 ) < p_sys
->i_magnet_accuracy
614 && abs( ps_piece_A
->i_BRy
- ps_piece_B
->i_BLy
) < p_sys
->i_magnet_accuracy
)
616 ps_piece_B
->i_left_shape
= 0;
617 ps_piece_A
->i_right_shape
= 6;
620 else if ( abs( ps_piece_A
->i_OLx
- ps_piece_B
->i_OLx
)<3 )
622 if ( abs( ps_piece_A
->i_OBy
- ps_piece_B
->i_OTy
+ 1 )<3
623 && abs( ps_piece_B
->i_TLx
- ps_piece_A
->i_BLx
) < p_sys
->i_magnet_accuracy
624 && abs( ps_piece_B
->i_TLy
- 1 - ps_piece_A
->i_BLy
) < p_sys
->i_magnet_accuracy
625 && abs( ps_piece_B
->i_TRx
- ps_piece_A
->i_BRx
) < p_sys
->i_magnet_accuracy
626 && abs( ps_piece_B
->i_TRy
- 1 - ps_piece_A
->i_BRy
) < p_sys
->i_magnet_accuracy
)
628 ps_piece_B
->i_top_shape
= 2;
629 ps_piece_A
->i_btm_shape
= 4;
635 /*****************************************************************************
636 * puzzle_solve_pces_accuracy: check if pieces are close to their final location
637 * and then adjust position accordingly
638 *****************************************************************************/
639 void puzzle_solve_pces_accuracy( filter_t
*p_filter
) {
640 filter_sys_t
*p_sys
= p_filter
->p_sys
;
642 p_sys
->i_solve_acc_loop
++;
643 if (p_sys
->i_solve_acc_loop
>= p_sys
->s_allocated
.i_pieces_nbr
) {
644 p_sys
->i_done_count
= p_sys
->i_tmp_done_count
;
645 p_sys
->i_tmp_done_count
= 0;
646 p_sys
->i_solve_acc_loop
= 0;
647 p_sys
->b_finished
= (p_sys
->i_done_count
== p_sys
->s_allocated
.i_pieces_nbr
);
650 piece_t
*ps_piece
= &p_sys
->ps_pieces
[p_sys
->i_solve_acc_loop
];
652 ps_piece
->b_finished
= false;
653 if ( ps_piece
->i_actual_mirror
== 1
654 && abs( ps_piece
->i_TRx
- ps_piece
->i_ORx
) < p_sys
->i_magnet_accuracy
655 && abs( ps_piece
->i_TRy
- ps_piece
->i_OTy
) < p_sys
->i_magnet_accuracy
656 && abs( ps_piece
->i_TLx
- ps_piece
->i_OLx
) < p_sys
->i_magnet_accuracy
657 && abs( ps_piece
->i_TLy
- ps_piece
->i_OTy
) < p_sys
->i_magnet_accuracy
)
659 uint32_t i_group_ID
= ps_piece
->i_group_ID
;
660 p_sys
->i_tmp_done_count
++;
662 for ( uint32_t i
= 0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++) {
663 ps_piece
= &p_sys
->ps_pieces
[i
];
664 if ( ( ps_piece
->i_group_ID
== i_group_ID
) && ( !ps_piece
->b_finished
) ) {
665 ps_piece
->ps_piece_in_plane
[0].i_actual_x
= ps_piece
->i_OLx
;
666 ps_piece
->ps_piece_in_plane
[0].i_actual_y
= ps_piece
->i_OTy
;
667 ps_piece
->i_actual_mirror
= +1;
668 puzzle_calculate_corners( p_filter
, i
);
669 ps_piece
->b_finished
= true;
675 /*****************************************************************************
676 * puzzle_sort_layers: sort pieces in order to see in foreground the
677 * standalone ones and those are at the wrong place
678 *****************************************************************************/
679 int puzzle_sort_layers( filter_t
*p_filter
)
681 filter_sys_t
*p_sys
= p_filter
->p_sys
;
684 for (uint32_t i_qty
= 1; i_qty
<= p_sys
->s_current_param
.i_pieces_nbr
; i_qty
++) {
685 /* pieces at the wrong place are in foreground */
686 for (uint32_t i_pce_loop
= 0; i_pce_loop
< p_sys
->s_current_param
.i_pieces_nbr
; i_pce_loop
++) {
687 uint32_t i_grp
= p_sys
->ps_pieces
[i_pce_loop
].i_group_ID
;
688 if ( p_sys
->pi_group_qty
[i_grp
] == (int32_t)i_qty
) {
689 bool b_check_ok
= true;
690 for (int32_t i_pce_check
= 0; i_pce_check
< i_idx
; i_pce_check
++)
691 if ( p_sys
->ps_pieces_tmp
[i_pce_check
].i_group_ID
== i_grp
)
694 for (uint32_t i_pce
= i_pce_loop
; i_pce
< p_sys
->s_current_param
.i_pieces_nbr
; i_pce
++)
695 if (( p_sys
->ps_pieces
[i_pce
].i_group_ID
== i_grp
) && !p_sys
->ps_pieces
[i_pce
].b_finished
) {
696 memcpy( &p_sys
->ps_pieces_tmp
[i_idx
], &p_sys
->ps_pieces
[i_pce
], sizeof(piece_t
));
701 /* pieces at the final location are in background */
702 for (uint32_t i_pce_loop
= 0; i_pce_loop
< p_sys
->s_current_param
.i_pieces_nbr
; i_pce_loop
++) {
703 uint32_t i_grp
= p_sys
->ps_pieces
[i_pce_loop
].i_group_ID
;
704 if ( p_sys
->pi_group_qty
[i_grp
] == (int32_t)i_qty
) {
705 bool b_check_ok
= true;
706 for (int32_t i_pce_check
= 0; i_pce_check
< i_idx
; i_pce_check
++)
707 if ( p_sys
->ps_pieces_tmp
[i_pce_check
].i_group_ID
== i_grp
&& p_sys
->ps_pieces_tmp
[i_pce_check
].b_finished
)
710 for (uint32_t i_pce
= i_pce_loop
; i_pce
< p_sys
->s_current_param
.i_pieces_nbr
; i_pce
++)
711 if (( p_sys
->ps_pieces
[i_pce
].i_group_ID
== i_grp
) && p_sys
->ps_pieces
[i_pce
].b_finished
) {
712 memcpy( &p_sys
->ps_pieces_tmp
[i_idx
], &p_sys
->ps_pieces
[i_pce
], sizeof(piece_t
));
719 free( p_filter
->p_sys
->ps_pieces
);
720 p_filter
->p_sys
->ps_pieces
= p_sys
->ps_pieces_tmp
;
721 p_sys
->ps_pieces_tmp
= malloc( sizeof( piece_t
) * p_sys
->s_allocated
.i_pieces_nbr
);
722 if (!p_sys
->ps_pieces_tmp
)
728 /*****************************************************************************
729 * puzzle_auto_solve: solve the puzzle depending on auto_solve_speed parameter
730 * = move one piece at the final location each time
731 * auto_solve_countdown is < 0
732 *****************************************************************************/
733 void puzzle_auto_solve( filter_t
*p_filter
)
735 filter_sys_t
*p_sys
= p_filter
->p_sys
;
737 if ( p_sys
->s_current_param
.i_auto_solve_speed
< 500 )
740 if ( --p_sys
->i_auto_solve_countdown_val
> 0 )
743 /* delay reached, preset next delay and proceed with puzzle_auto_solve */
744 p_sys
->i_auto_solve_countdown_val
= init_countdown(p_sys
->s_current_param
.i_auto_solve_speed
);
746 /* random piece to be moved */
747 int32_t i_start
= ((unsigned)vlc_mrand48()) % p_sys
->s_allocated
.i_pieces_nbr
;
749 /* here the computer will help player by placing the piece at the final location */
750 for (uint32_t i_l
= 0; i_l
< p_sys
->s_allocated
.i_pieces_nbr
; i_l
++) {
751 int32_t i
= ( i_l
+ i_start
) % p_sys
->s_allocated
.i_pieces_nbr
;
752 if ( !p_sys
->ps_pieces
[i
].b_finished
) {
753 for (uint32_t j
= 0; j
< p_sys
->s_allocated
.i_pieces_nbr
; j
++) {
754 if ( p_sys
->ps_pieces
[j
].i_group_ID
== p_sys
->ps_pieces
[i
].i_group_ID
) {
755 p_sys
->ps_pieces
[j
].i_actual_angle
= 0;
756 p_sys
->ps_pieces
[j
].i_actual_mirror
= +1;
757 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
;
758 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
;
759 puzzle_calculate_corners( p_filter
, j
);
767 /*****************************************************************************
768 * puzzle_auto_shuffle: shuffle the pieces on the desk depending on
769 * auto_shuffle_speed parameter
770 * = random move of one piece each time
771 * auto_shuffle_countdown is < 0
772 *****************************************************************************/
773 void puzzle_auto_shuffle( filter_t
*p_filter
)
775 filter_sys_t
*p_sys
= p_filter
->p_sys
;
777 if ( p_sys
->s_current_param
.i_auto_shuffle_speed
< 500 )
780 if ( --p_sys
->i_auto_shuffle_countdown_val
> 0 )
783 /* delay reached, preset next delay and proceed with puzzle_auto_shuffle */
784 p_sys
->i_auto_shuffle_countdown_val
= init_countdown(p_sys
->s_current_param
.i_auto_shuffle_speed
);
786 /* random piece to be moved */
787 int32_t i_start
= ((unsigned)vlc_mrand48()) % p_sys
->s_allocated
.i_pieces_nbr
;
789 for (uint32_t i_l
= 0; i_l
< p_sys
->s_allocated
.i_pieces_nbr
; i_l
++){
790 int32_t i
= ( i_l
+ i_start
) % p_sys
->s_allocated
.i_pieces_nbr
;
792 /* find one piece which is part of one group */
793 if ( p_sys
->pi_group_qty
[p_sys
->ps_pieces
[i
].i_group_ID
] > 1 ) {
794 /* find an empty group to be used by this dismantled piece */
795 uint32_t i_new_group
;
796 for ( i_new_group
= 0 ; i_new_group
< p_sys
->s_allocated
.i_pieces_nbr
; i_new_group
++ )
797 if ( p_sys
->pi_group_qty
[i_new_group
] == 0 )
799 p_sys
->ps_pieces
[i
].i_group_ID
= i_new_group
;
800 p_sys
->ps_pieces
[i
].b_finished
= false;
802 /* random rotate & mirror */
803 switch ( p_sys
->s_current_param
.i_rotate
)
806 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 );
809 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 );
812 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 );
817 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_actual_x
=
818 p_sys
->ps_desk_planes
[0].i_border_width
819 + ( (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
)
820 + p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_width
/ 2 * ( 1 - p_sys
->ps_pieces
[i
].i_step_x_x
)
821 - (p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_lines
/ 2) * p_sys
->ps_pieces
[i
].i_step_y_x
;
822 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_actual_y
=
823 p_sys
->ps_desk_planes
[0].i_border_lines
824 + ( (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
)
825 + p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_lines
/ 2 * ( 1 - p_sys
->ps_pieces
[i
].i_step_y_y
)
826 - (p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_width
/ 2) * p_sys
->ps_pieces
[i
].i_step_x_y
;
828 /* redefine shapes */
829 uint32_t i_left_pce
= 0;
830 uint32_t i_right_pce
= 6;
831 uint32_t i_top_pce
= 2;
832 uint32_t i_btm_pce
= 4;
835 for (int32_t i_row
= 0; i_row
< p_sys
->s_allocated
.i_rows
; i_row
++)
836 for (int32_t i_col
= 0; i_col
< p_sys
->s_allocated
.i_cols
; i_col
++) {
837 if (p_sys
->ps_pieces
[i
].i_original_row
== p_sys
->ps_pieces
[i_pce
].i_original_row
) {
838 if (p_sys
->ps_pieces
[i
].i_original_col
== p_sys
->ps_pieces
[i_pce
].i_original_col
- 1)
840 else if (p_sys
->ps_pieces
[i
].i_original_col
== p_sys
->ps_pieces
[i_pce
].i_original_col
+ 1)
843 else if (p_sys
->ps_pieces
[i
].i_original_col
== p_sys
->ps_pieces
[i_pce
].i_original_col
) {
844 if (p_sys
->ps_pieces
[i
].i_original_row
== p_sys
->ps_pieces
[i_pce
].i_original_row
- 1)
846 else if (p_sys
->ps_pieces
[i
].i_original_row
== p_sys
->ps_pieces
[i_pce
].i_original_row
+ 1)
852 if ((p_sys
->ps_pieces
[i
].i_left_shape
== 0) && (p_sys
->ps_pieces
[i
].i_original_col
!= 0)) {
853 p_sys
->ps_pieces
[i_left_pce
].i_right_shape
= 6 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
854 p_sys
->ps_pieces
[i
].i_left_shape
= (p_sys
->ps_pieces
[i_left_pce
].i_right_shape
- 6 ) ^ 0x01;
857 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)) {
858 p_sys
->ps_pieces
[i
].i_right_shape
= 6 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
859 p_sys
->ps_pieces
[i_right_pce
].i_left_shape
= (p_sys
->ps_pieces
[i
].i_right_shape
- 6 ) ^ 0x01;
862 if ((p_sys
->ps_pieces
[i
].i_top_shape
== 2) && (p_sys
->ps_pieces
[i
].i_original_row
!= 0)) {
863 p_sys
->ps_pieces
[i_top_pce
].i_btm_shape
= 4 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
864 p_sys
->ps_pieces
[i
].i_top_shape
= (p_sys
->ps_pieces
[i_top_pce
].i_btm_shape
- 2 ) ^ 0x01;
867 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)) {
868 p_sys
->ps_pieces
[i
].i_btm_shape
= 4 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
869 p_sys
->ps_pieces
[i_btm_pce
].i_top_shape
= (p_sys
->ps_pieces
[i
].i_btm_shape
- 2 ) ^ 0x01;
872 puzzle_calculate_corners( p_filter
, i
);
878 /*****************************************************************************
879 * puzzle_save: save pieces location in memory
880 *****************************************************************************/
881 save_game_t
* puzzle_save(filter_t
*p_filter
)
883 filter_sys_t
*p_sys
= p_filter
->p_sys
;
885 save_game_t
*ps_save_game
= calloc(1, sizeof(*ps_save_game
));
889 ps_save_game
->i_cols
= p_sys
->s_allocated
.i_cols
;
890 ps_save_game
->i_rows
= p_sys
->s_allocated
.i_rows
;
891 ps_save_game
->i_rotate
= p_sys
->s_allocated
.i_rotate
;
893 ps_save_game
->ps_pieces
= calloc( ps_save_game
->i_cols
* ps_save_game
->i_rows
, sizeof(*ps_save_game
->ps_pieces
));
894 if (!ps_save_game
->ps_pieces
) {
899 int32_t i_border_width
= p_sys
->ps_desk_planes
[0].i_border_width
;
900 int32_t i_border_lines
= p_sys
->ps_desk_planes
[0].i_border_lines
;
902 for (int32_t i_pce
= 0; i_pce
< ps_save_game
->i_cols
* ps_save_game
->i_rows
; i_pce
++) {
903 ps_save_game
->ps_pieces
[i_pce
].i_original_row
= p_sys
->ps_pieces
[i_pce
].i_original_row
;
904 ps_save_game
->ps_pieces
[i_pce
].i_original_col
= p_sys
->ps_pieces
[i_pce
].i_original_col
;
905 ps_save_game
->ps_pieces
[i_pce
].i_top_shape
= p_sys
->ps_pieces
[i_pce
].i_top_shape
;
906 ps_save_game
->ps_pieces
[i_pce
].i_btm_shape
= p_sys
->ps_pieces
[i_pce
].i_btm_shape
;
907 ps_save_game
->ps_pieces
[i_pce
].i_right_shape
= p_sys
->ps_pieces
[i_pce
].i_right_shape
;
908 ps_save_game
->ps_pieces
[i_pce
].i_left_shape
= p_sys
->ps_pieces
[i_pce
].i_left_shape
;
909 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
);
910 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
);
911 ps_save_game
->ps_pieces
[i_pce
].i_actual_angle
= p_sys
->ps_pieces
[i_pce
].i_actual_angle
;
912 ps_save_game
->ps_pieces
[i_pce
].i_actual_mirror
= p_sys
->ps_pieces
[i_pce
].i_actual_mirror
;
918 void puzzle_load( filter_t
*p_filter
, save_game_t
*ps_save_game
)
920 filter_sys_t
*p_sys
= p_filter
->p_sys
;
922 if (p_sys
->s_current_param
.i_cols
!= ps_save_game
->i_cols
923 || p_sys
->s_allocated
.i_rows
!= ps_save_game
->i_rows
924 || p_sys
->s_allocated
.i_rotate
!= ps_save_game
->i_rotate
)
927 int32_t i_border_width
= p_sys
->ps_desk_planes
[0].i_border_width
;
928 int32_t i_border_lines
= p_sys
->ps_desk_planes
[0].i_border_lines
;
930 for (uint32_t i_pce
=0; i_pce
< p_sys
->s_allocated
.i_pieces_nbr
; i_pce
++) {
931 for (uint32_t i
=0; i
< p_sys
->s_allocated
.i_pieces_nbr
; i
++)
932 if ( p_sys
->ps_pieces
[i
].i_original_row
== ps_save_game
->ps_pieces
[i_pce
].i_original_row
933 && p_sys
->ps_pieces
[i
].i_original_col
== ps_save_game
->ps_pieces
[i_pce
].i_original_col
)
935 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_actual_x
= i_border_width
936 + ((float)p_sys
->ps_desk_planes
[0].i_width
- 2 * i_border_width
)
937 * ps_save_game
->ps_pieces
[i_pce
].f_pos_x
;
938 p_sys
->ps_pieces
[i
].ps_piece_in_plane
[0].i_actual_y
= i_border_lines
939 + ((float)p_sys
->ps_desk_planes
[0].i_lines
- 2 * i_border_lines
)
940 * ps_save_game
->ps_pieces
[i_pce
].f_pos_y
;
942 p_sys
->ps_pieces
[i
].i_top_shape
= ps_save_game
->ps_pieces
[i_pce
].i_top_shape
;
943 p_sys
->ps_pieces
[i
].i_btm_shape
= ps_save_game
->ps_pieces
[i_pce
].i_btm_shape
;
944 p_sys
->ps_pieces
[i
].i_right_shape
= ps_save_game
->ps_pieces
[i_pce
].i_right_shape
;
945 p_sys
->ps_pieces
[i
].i_left_shape
= ps_save_game
->ps_pieces
[i_pce
].i_left_shape
;
946 p_sys
->ps_pieces
[i
].i_actual_angle
= ps_save_game
->ps_pieces
[i_pce
].i_actual_angle
;
947 p_sys
->ps_pieces
[i
].i_actual_mirror
= ps_save_game
->ps_pieces
[i_pce
].i_actual_mirror
;
948 p_sys
->ps_pieces
[i
].i_group_ID
= i_pce
;
949 p_sys
->ps_pieces
[i
].b_finished
= false;
951 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
952 - 2*i_border_width
) * ps_save_game
->ps_pieces
[i_pce
].f_pos_x
;
953 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
954 - 2*i_border_lines
) * ps_save_game
->ps_pieces
[i_pce
].f_pos_y
;
955 puzzle_calculate_corners( p_filter
, i
);
961 for (uint32_t i_pce
=0; i_pce
< p_sys
->s_allocated
.i_pieces_nbr
; i_pce
++) {
962 /* redefine shapes */
963 uint32_t i_left_pce
= 0;
964 uint32_t i_right_pce
= 6;
965 uint32_t i_top_pce
= 2;
966 uint32_t i_btm_pce
= 4;
968 uint32_t i_pce_pair
= 0;
969 for (int32_t i_row
= 0; i_row
< p_sys
->s_allocated
.i_rows
; i_row
++)
970 for (int32_t i_col
= 0; i_col
< p_sys
->s_allocated
.i_cols
; i_col
++) {
971 if (p_sys
->ps_pieces
[i_pce
].i_original_row
== p_sys
->ps_pieces
[i_pce_pair
].i_original_row
) {
972 if (p_sys
->ps_pieces
[i_pce
].i_original_col
== p_sys
->ps_pieces
[i_pce_pair
].i_original_col
- 1)
973 i_right_pce
= i_pce_pair
;
974 else if (p_sys
->ps_pieces
[i_pce
].i_original_col
== p_sys
->ps_pieces
[i_pce_pair
].i_original_col
+ 1)
975 i_left_pce
= i_pce_pair
;
977 else if (p_sys
->ps_pieces
[i_pce
].i_original_col
== p_sys
->ps_pieces
[i_pce_pair
].i_original_col
) {
978 if (p_sys
->ps_pieces
[i_pce
].i_original_row
== p_sys
->ps_pieces
[i_pce_pair
].i_original_row
- 1)
979 i_btm_pce
= i_pce_pair
;
980 else if (p_sys
->ps_pieces
[i_pce
].i_original_row
== p_sys
->ps_pieces
[i_pce_pair
].i_original_row
+ 1)
981 i_top_pce
= i_pce_pair
;
986 if ((p_sys
->ps_pieces
[i_pce
].i_left_shape
== 0) && (p_sys
->ps_pieces
[i_pce
].i_original_col
!= 0)) {
987 p_sys
->ps_pieces
[i_left_pce
].i_right_shape
= 6 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
988 p_sys
->ps_pieces
[i_pce
].i_left_shape
= (p_sys
->ps_pieces
[i_left_pce
].i_right_shape
- 6 ) ^ 0x01;
991 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)) {
992 p_sys
->ps_pieces
[i_pce
].i_right_shape
= 6 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
993 p_sys
->ps_pieces
[i_right_pce
].i_left_shape
= (p_sys
->ps_pieces
[i_pce
].i_right_shape
- 6 ) ^ 0x01;
996 if ((p_sys
->ps_pieces
[i_pce
].i_top_shape
== 2) && (p_sys
->ps_pieces
[i_pce
].i_original_row
!= 0)) {
997 p_sys
->ps_pieces
[i_top_pce
].i_btm_shape
= 4 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
998 p_sys
->ps_pieces
[i_pce
].i_top_shape
= (p_sys
->ps_pieces
[i_top_pce
].i_btm_shape
- 2 ) ^ 0x01;
1001 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)) {
1002 p_sys
->ps_pieces
[i_pce
].i_btm_shape
= 4 + 8 + 8*(( (unsigned) vlc_mrand48()) % ( SHAPES_QTY
) ) + (vlc_mrand48() & 0x01);
1003 p_sys
->ps_pieces
[i_btm_pce
].i_top_shape
= (p_sys
->ps_pieces
[i_pce
].i_btm_shape
- 2 ) ^ 0x01;