14 #define NCYCLES 1000000
16 #define SORTER_MOVE_TRIES 100
17 #define FREE_PER_ITEM 50
19 typedef enum {A
=0, EMPTY
, SORTER
} item_t
;
28 typedef struct board_s board_t
;
34 typedef struct sorter_s sorter_t
;
36 void count_item (board_t
*, item_t
*, unsigned int *);
37 void drop_item (unsigned int, unsigned int, board_t
*, item_t
*);
38 void erase_board (board_t
*);
39 void fetch_item(unsigned int, unsigned int, item_t
*);
40 void finish_board(board_t
*);
41 void move_sorter (board_t
*, sorter_t
*);
42 void peek_item (unsigned int, unsigned int, board_t
*, item_t
*);
43 void pick_item (unsigned int, unsigned int, board_t
*, item_t
*);
44 void poke_item (unsigned int, unsigned int, board_t
*, item_t
);
45 void print_board (board_t
*);
46 void print_item (unsigned int, unsigned int, item_t
);
47 void launch_sorter (board_t
*);
48 void setup_board(board_t
*);
50 /* Erase the output medium. */
51 void erase_board (board_t
*board
)
57 void move_sorter(board_t
*board
, sorter_t
*sorter
)
59 assert(sorter
!= NULL
);
60 assert(sorter
->line
< HEIGHT
);
61 assert(sorter
->column
< WIDTH
);
64 unsigned int newcolumn
, newline
;
66 item_t item
, sorter_item
;
70 /* Select random displacement. */
74 newcolumn
= (sorter
->column
+ (h
+WIDTH
)) % WIDTH
;
75 newline
= (sorter
->line
+ (v
+HEIGHT
)) % HEIGHT
;
77 peek_item(newcolumn
, newline
, board
, &item
);
79 } while ((item
!= EMPTY
) && (ncycles
< SORTER_MOVE_TRIES
));
81 /* If sorter failed to move, respawn in random position */
82 if (ncycles
== SORTER_MOVE_TRIES
) {
84 newcolumn
= random()%WIDTH
;
85 newline
= random()%HEIGHT
;
86 peek_item(newcolumn
, newline
, board
, &item
);
87 } while (item
!= EMPTY
);
92 /* Don't reset the item if sorter just droped one. */
93 /* If an item was droped, it will be different of SORTER. */
94 peek_item(sorter
->column
, sorter
->line
, board
, &sorter_item
);
95 if (sorter_item
== SORTER
) {
96 poke_item (sorter
->column
, sorter
->line
, board
, EMPTY
);
98 poke_item(newcolumn
, newline
, board
, SORTER
);
99 sorter
->column
= newcolumn
;
100 sorter
->line
= newline
;
102 assert(sorter
->line
< HEIGHT
);
103 assert(sorter
->column
< WIDTH
);
106 void launch_sorter (board_t
*board
)
114 /* Place sorter in some free position. */
116 column
= random()%WIDTH
;
117 line
= random()%HEIGHT
;
118 peek_item(column
, line
, board
, &item
);
119 } while (item
!= EMPTY
);
120 poke_item(column
, line
, board
, SORTER
);
121 sorter
.column
= column
;
124 for (itera
= 0; itera
<= NCYCLES
; ++itera
) {
125 //for (itera = 0; 0==0; ++itera) {
127 move_sorter(board
, &sorter
);
128 pick_item(sorter
.column
, sorter
.line
, board
, &item
);
130 } while (item
== EMPTY
);
132 /* because the sorter allways moves, if it drops the item it will not
133 * remain on the top of it */
134 while (item
!= EMPTY
) {
135 drop_item(sorter
.column
, sorter
.line
, board
, &item
);
136 move_sorter(board
, &sorter
);
140 /* leave the premisses */
141 //for (r = 0; (r < 10); ++r) {
142 // move(board, sorter);
147 /* Try to pick an item. Don't pick other sorters :) */
148 void pick_item (unsigned int column
, unsigned int line
, board_t
*board
, item_t
*item
)
150 assert (board
!= NULL
);
151 assert (board
->size_valid
);
152 assert (board
->surface_valid
);
153 assert (column
< board
->width
);
154 assert (line
< board
->height
);
155 assert (item
!= NULL
);
156 assert (*item
== EMPTY
);
158 int newcolumn
, newline
;
160 int h
, v
; /* h: horizontal; v: vertical */
162 for (h
= -1; (h
<= 1) && (*item
== EMPTY
); ++h
) {
163 for (v
= -1; (v
<= 1) && (*item
== EMPTY
); ++v
) {
164 /* newcolumn and newline need to be allawys positive */
165 newcolumn
= (column
+(h
+WIDTH
))%WIDTH
;
166 newline
= (line
+(v
+HEIGHT
))%HEIGHT
;
168 //pthread_mutex_lock(&(tabuleiro.mutex[newcolumn][newline]));
169 peek_item(newcolumn
, newline
, board
, &newitem
);
170 if((newitem
!= EMPTY
) && (newitem
!= SORTER
)) {
172 poke_item(newcolumn
, newline
, board
, EMPTY
);
173 //pthread_mutex_unlock(&(tabuleiro.mutex[newcolumn][newline]));
174 /* we have the item */
176 //pthread_mutex_unlock(&(tabuleiro.mutex[newcolumn][newline]));
180 /* we either pick an item or leave it as it is */
181 assert ((*item
== newitem
) || (*item
== EMPTY
));
182 assert (*item
!= SORTER
);
185 /* Try to drop one item. The item needs to be droped in a position adjacent to
188 void drop_item (unsigned int column
, unsigned int line
, board_t
*board
, item_t
*item
)
190 assert (board
!= NULL
);
191 assert (board
->size_valid
);
192 assert (board
->surface_valid
);
193 assert (column
< board
->width
);
194 assert (line
< board
->height
);
195 assert (item
!= NULL
);
196 assert (*item
!= EMPTY
);
197 assert (*item
!= SORTER
);
199 int newcolumn
, newline
;
200 int h
, v
; /* h: horizontal, v: vertical */
203 for (h
= -1; (h
<= 1) && (*item
!= EMPTY
); ++h
) {
204 for (v
= -1; (v
<= 1) && (*item
!= EMPTY
); ++v
) {
205 /* newcolumn and newline need to be allawys positive */
206 newcolumn
= (column
+h
+WIDTH
)%WIDTH
;
207 newline
= (line
+v
+HEIGHT
)%HEIGHT
;
209 //pthread_mutex_lock(&(tabuleiro.mutex[xnovo][ynovo]));
210 peek_item(newcolumn
, newline
, board
, &newitem
);
211 if(newitem
== *item
) {
212 poke_item(column
, line
, board
, newitem
);
214 /* and the item is down */
216 //pthread_mutex_unlock(&(tabuleiro.mutex[xnovo][ynovo]));
219 //pthread_mutex_unlock(&(tabuleiro.mutex[column][line]));
222 /* Print the base of the board, without any items. */
223 void print_board(board_t
*board
)
225 assert(board
->size_valid
);
226 assert(board
->surface_valid
);
229 conglMoveCursor(1, 1);
232 void print_item(unsigned int column
, unsigned int line
, item_t item
)
234 struct properties_s
{
239 typedef struct properties_s properties_t
;
241 properties_t properties
[] = {
242 {congl_magenta
, congl_white
, ' '},
243 {congl_green
, congl_white
, ' '},
244 {congl_black
, congl_white
, ' '}
245 //{'i'}, {'f'}, {'s'}
250 p
= properties
[item
];
251 conglDrawCharFull(column
+1, line
+1, p
.symbol
, p
.fg
, p
.bg
);
253 //printf("%c: %d,%d\n", p.symbol, line, column);
256 /* Read an item from the board. */
257 void peek_item (unsigned int column
, unsigned int line
, board_t
*board
, item_t
*item
)
259 assert(board
!= NULL
);
260 assert(board
->size_valid
);
261 assert(board
->surface_valid
);
262 assert(line
< board
->height
);
263 assert(column
< board
->width
);
264 assert(item
!= NULL
);
266 *item
= board
->surface
[line
][column
];
268 assert(*item
== board
->surface
[line
][column
]);
271 /* Write an item in position (line,column) of the board. At the same time update
274 void poke_item (unsigned int column
, unsigned int line
, board_t
*board
, item_t item
)
276 assert(board
!= NULL
);
277 assert(board
->size_valid
);
278 assert(board
->surface_valid
);
279 assert(line
< board
->height
);
280 assert(column
< board
->width
);
282 board
->surface
[line
][column
] = item
;
284 print_item (column
, line
, item
);
286 assert(board
->surface
[line
][column
] == item
);
289 /* Fetch an item from somewhere. The purpose of this functin is to allow the
290 * user to load one pattern every time the program runs. For now all items are
293 void fetch_item(unsigned int column
, unsigned int line
, item_t
*item
)
295 assert(item
!= NULL
);
299 /* generate one block in every FREE_PER_ITEM board cells */
300 number
= random()%FREE_PER_ITEM
;
310 void setup_board(board_t
*board
)
312 assert (board
->size_valid
);
313 assert (!board
->surface_valid
);
315 unsigned int line
, column
;
318 //printf("Preparing board.\n");
320 /* allocate space for the board */
321 board
->surface
= calloc (board
->height
, sizeof(board
->surface
));
322 if (board
->surface
== NULL
) {
323 perror("board_setup");
326 for (line
= 0; line
< board
->height
; ++line
) {
327 board
->surface
[line
] = calloc (board
->width
, sizeof(item_t
));
328 if (board
->surface
[line
] == NULL
) {
329 perror("board_setup");
333 board
->surface_valid
= true;
335 //printf("Printing board.\n");
337 //printf("Board printed.\n");
339 /* fill the board with initial values */
340 for (line
= 0; line
< board
->height
; ++line
) {
341 for (column
= 0; column
< board
->width
; ++column
) {
342 fetch_item(line
, column
, &item
);
343 poke_item(column
, line
, board
, item
);
347 assert (board
->surface_valid
);
350 void finish_board (board_t
*board
)
352 assert (board
->surface_valid
);
356 for (line
= 0; line
< board
->height
; ++line
) {
357 free (board
->surface
[line
]);
359 free (board
->surface
);
360 board
->surface_valid
= false;
364 assert (!board
->surface_valid
);
367 void count_items(board_t
*board
, item_t
*item
, unsigned int *nitems
)
369 assert (board
!= NULL
);
370 assert (item
!= NULL
);
371 assert (nitems
!= NULL
);
373 unsigned int column
, line
;
378 for (line
= 0; line
< board
->height
; ++line
) {
379 for (column
= 0; column
< board
->width
; ++column
) {
380 peek_item(column
, line
, board
, &this_item
);
381 if (this_item
== *item
) count
++;
388 int main (int argc
, char *argv
[])
391 unsigned int nitems_begin
, nitems_finish
;
395 board
.height
= HEIGHT
;
396 board
.size_valid
= true;
397 board
.surface_valid
= false;
399 /* intialize random number generator */
400 srandom((unsigned int)time(NULL
));
402 setup_board (&board
);
406 count_items(&board
, &item
, &nitems_begin
);
409 launch_sorter(&board
);
411 count_items(&board
, &item
, &nitems_finish
);
413 /* make shure the sorter isn't eating items */
414 assert(nitems_begin
== nitems_finish
);
416 finish_board (&board
);
418 printf("All good.\n");