Subversion Repositories Kolibri OS

Rev

Rev 5231 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5229 raandoom 1
#include "board.h"
2
 
3
rect base_cell = {0};
4
tile null_tile = {0};
5
 
6
 
7
struct {
8
    rect    draw;                       // background rect
9
    rect    cell_map[BOARD_MAP_SIZE];   // background cells array
10
    tile    tile_map[BOARD_MAP_SIZE];   // tiles array
11
    __u16   empty_index[BOARD_MAP_SIZE];// empty cells indexes
12
    __u16   empty_count;                // empty cells count
13
    __u32   score;
14
} board = {0};
15
 
16
// Get tile index for row and column
17
__u16 board_index(__u16 row, __u16 column) {
18
    return column + row * BOARD_COUNT;
19
}
20
 
21
// Get tile position (as point with eow and column) for index
22
point board_position(__u16 index) {
23
    point p = {
24
        .x = index % BOARD_COUNT,
25
        .y = index / BOARD_COUNT
26
    };
27
    return p;
28
}
29
 
30
// Calculate cell rect for row and column
31
rect position2cell(point p) {
32
    rect c = {0};
33
    c.width = base_cell.width;
34
    c.height = base_cell.height;
35
    c.x = board.draw.x + BOARD_SPACING + p.x * (c.width + BOARD_SPACING);
36
    c.y = board.draw.y + BOARD_SPACING + p.y * (c.height + BOARD_SPACING);
37
    return c;
38
}
39
 
40
// Update information about empty cells
41
void board_update_empty_info();
42
 
43
// Represent tile array as pointers array
44
void board_to_tempboard(tile* temp[]);
45
 
46
// Fill tile array with tiles from pointers array
47
void board_from_tempboard(tile* temp[], __u8 forward);
48
 
49
// Move tile inside a pointer array
50
void tempboard_move_tile(tile* temp[], __u16 from, __u16 to);
51
 
52
// Merge tiles inside a pointer array
53
void tempboard_merge_tile(tile* temp[], __u16 from, __u16 to);
54
 
55
// Random number generator
56
__u32 random_u32(__u32 max);
57
 
58
void board_init(rect* r)
59
{
60
    // seed for random number generator
61
    srand(__menuet__getsystemclock());
62
 
63
    board.score = 0;
64
    board.draw = *r;
65
 
66
    __u16 cell_size = (r->width - BOARD_SPACING * (BOARD_COUNT + 1)) / BOARD_COUNT;
67
    base_cell.width = cell_size;
68
    base_cell.height = cell_size;
69
 
70
    null_tile.value = 0;
71
    null_tile.animate = false;
72
    null_tile.ani_step = ANIM_STEP;
73
    null_tile.merged = false;
74
 
75
    __u16 i = 0;
76
    for (i = 0; i < BOARD_MAP_SIZE; i++)
77
    {
78
        board.cell_map[i] = position2cell(board_position(i));
79
        board.tile_map[i] = null_tile;
80
    }
81
 
82
    i = 0;
83
    for (i = 0; i < START_COUNT; i++)
84
    {
85
        board_add_random_tile();
86
    }
87
 
88
    board_redraw();
89
}
90
 
91
void board_redraw()
92
{
93
    __u16 i = 0;
94
    __u8 animate = false;
95
    __u8 last_animate = false;
96
    do
97
    {
98
        vsync();
99
        rect_draw(&board.draw,BOARD_BG_COLOR);
100
 
101
        for (i = 0; i < BOARD_MAP_SIZE; i++)
102
        {
103
            rect_draw(&board.cell_map[i],CELL_COLOR);
104
        }
105
 
106
        animate = false;
107
        last_animate = false;
108
        for (i = 0; i < BOARD_MAP_SIZE; i++)
109
        {
110
            tile* t = &board.tile_map[i];
111
            last_animate = tile_draw(t);
112
            if (last_animate)
113
            {
114
                animate = last_animate;
115
            }
116
        }
117
 
118
        if (animate)
119
        {
120
            __menuet__delay100(ANIM_DELAY);
121
        }
122
    }
123
    while (animate);
124
}
125
 
126
__u8 board_up()
127
{
128
    __u8 moved = false;
129
 
130
    __u16 row = 0;
131
    __u16 column = 0;
132
    __u16 ind = 0;
133
    __u16 preind = 0;
134
    tile* indtile = 0;
135
    tile* pretile = 0;
136
 
137
    tile* temp_board[BOARD_MAP_SIZE] = {0};
138
    board_to_tempboard(temp_board);
139
 
140
    for (column = 0; column < BOARD_COUNT; column++)
141
    {
142
        for (row = 0; row < BOARD_COUNT; row++)
143
        {
144
            if (row > 0)
145
            {
146
                ind = board_index(row,column);
147
                indtile = temp_board[ind];
148
                if (indtile)
149
                {
150
                    preind = board_index(row - 1,column);
151
                    pretile = temp_board[preind];
152
                    if (!pretile)
153
                    {
154
                        moved = true;
155
                        tempboard_move_tile(temp_board,ind,preind);
156
                        row = 0;
157
                    }
158
                    else if (tile_mergeable(indtile,pretile))
159
                    {
160
                        moved = true;
161
                        board.score += indtile->value * 2;
162
                        tempboard_merge_tile(temp_board,ind,preind);
163
                        row = 0;
164
                    }
165
                }
166
            }
167
        }
168
    }
169
 
170
    board_from_tempboard(temp_board,true);
171
 
172
    return moved;
173
}
174
 
175
__u8 board_down()
176
{
177
    __u8 moved = false;
178
 
179
    __u16 row = 0;
180
    __u16 column = 0;
181
    __u16 ind = 0;
182
    __u16 preind = 0;
183
    tile* indtile = 0;
184
    tile* pretile = 0;
185
 
186
    tile* temp_board[BOARD_MAP_SIZE] = {0};
187
    board_to_tempboard(temp_board);
188
 
189
    for (column = 0; column < BOARD_COUNT; column++)
190
    {
191
        row = BOARD_COUNT;
192
        while (row--)
193
        {
194
            if ((BOARD_COUNT - row) > 1)
195
            {
196
                ind = board_index(row,column);
197
                indtile = temp_board[ind];
198
                if (indtile)
199
                {
200
                    preind = board_index(row + 1,column);
201
                    pretile = temp_board[preind];
202
                    if (!pretile)
203
                    {
204
                        moved = true;
205
                        tempboard_move_tile(temp_board,ind,preind);
206
                        row = BOARD_COUNT;
207
                    }
208
                    else if (tile_mergeable(indtile,pretile))
209
                    {
210
                        moved = true;
211
                        board.score += indtile->value * 2;
212
                        tempboard_merge_tile(temp_board,ind,preind);
213
                        row = BOARD_COUNT;
214
                    }
215
                }
216
            }
217
        }
218
    }
219
 
220
    board_from_tempboard(temp_board,false);
221
 
222
    return moved;
223
}
224
 
225
__u8 board_left()
226
{
227
    __u8 moved = false;
228
 
229
    __u16 row = 0;
230
    __u16 column = 0;
231
    __u16 ind = 0;
232
    __u16 preind = 0;
233
    tile* indtile = 0;
234
    tile* pretile = 0;
235
 
236
    tile* temp_board[BOARD_MAP_SIZE] = {0};
237
    board_to_tempboard(temp_board);
238
 
239
    for (row = 0; row < BOARD_COUNT; row++)
240
    {
241
        for (column = 0; column < BOARD_COUNT; column++)
242
        {
243
            if (column > 0)
244
            {
245
                ind = board_index(row,column);
246
                indtile = temp_board[ind];
247
                if (indtile)
248
                {
249
                    preind = board_index(row,column - 1);
250
                    pretile = temp_board[preind];
251
                    if (!pretile)
252
                    {
253
                        moved = true;
254
                        tempboard_move_tile(temp_board,ind,preind);
255
                        column = 0;
256
                    }
257
                    else if (tile_mergeable(indtile,pretile))
258
                    {
259
                        moved = true;
260
                        board.score += indtile->value * 2;
261
                        tempboard_merge_tile(temp_board,ind,preind);
262
                        column = 0;
263
                    }
264
                }
265
            }
266
        }
267
    }
268
 
269
    board_from_tempboard(temp_board,true);
270
 
271
    return moved;
272
}
273
 
274
__u8 board_right()
275
{
276
    __u8 moved = false;
277
 
278
    __u16 row = 0;
279
    __u16 column = 0;
280
    __u16 ind = 0;
281
    __u16 preind = 0;
282
    tile* indtile = 0;
283
    tile* pretile = 0;
284
 
285
    tile* temp_board[BOARD_MAP_SIZE] = {0};
286
    board_to_tempboard(temp_board);
287
 
288
    for (row = 0; row < BOARD_COUNT; row++)
289
    {
290
        column = BOARD_COUNT;
291
        while (column--)
292
        {
293
            if ((BOARD_COUNT - column) > 1)
294
            {
295
                ind = board_index(row,column);
296
                indtile = temp_board[ind];
297
                if (indtile)
298
                {
299
                    preind = board_index(row,column + 1);
300
                    pretile = temp_board[preind];
301
                    if (!pretile)
302
                    {
303
                        moved = true;
304
                        tempboard_move_tile(temp_board,ind,preind);
305
                        column = BOARD_COUNT;
306
                    }
307
                    else if (tile_mergeable(indtile,pretile))
308
                    {
309
                        moved = true;
310
                        board.score += indtile->value * 2;
311
                        tempboard_merge_tile(temp_board,ind,preind);
312
                        column = BOARD_COUNT;
313
                    }
314
                }
315
            }
316
        }
317
    }
318
 
319
    board_from_tempboard(temp_board,false);
320
 
321
    return moved;
322
}
323
 
324
__u8 board_add_random_tile()
325
{
326
    board_update_empty_info();
327
    if (board.empty_count)
328
    {
329
        __u16 rnd_av = random_u32(board.empty_count);
330
        rnd_av = board.empty_index[rnd_av];
331
 
332
        tile* av_tile = &board.tile_map[rnd_av];
333
        av_tile->value = (random_u32(10) < 9) ? 2 : 4;
334
 
335
        av_tile->animate = true;
336
        av_tile->ani_step = 5;
337
        av_tile->transition = position2cell(board_position(rnd_av));
338
        av_tile->cell.x = av_tile->transition.x + base_cell.width / 2;
339
        av_tile->cell.y = av_tile->transition.y + base_cell.height / 2;
340
        av_tile->cell.width = 0;
341
        av_tile->cell.height = 0;
342
    }
343
    return board.empty_count;
344
}
345
 
346
__u8 board_has_moves()
347
{
348
    __u16 ind = 0;
349
    __u16 next = 0;
350
    __u16 step = 0;
351
    __u16 pos = 0;
352
    for (step = 0; step < BOARD_COUNT; step++)
353
    {
354
        for (pos = 0; pos < BOARD_COUNT; pos++)
355
        {
356
            // check horizontal
357
            ind = board_index(step,pos);
358
            next = board_index(step,pos + 1);
359
 
360
            if (!board.tile_map[ind].value ||
361
                    (((pos + 1) < BOARD_COUNT) &&
362
                     (!board.tile_map[next].value ||
363
                      (board.tile_map[ind].value == board.tile_map[next].value)
364
                      )
365
                     )
366
                    )
367
                return true;
368
 
369
            // check vertical
370
            ind = board_index(pos,step);
371
            next = board_index(pos + 1,step);
372
 
373
            if (!board.tile_map[ind].value ||
374
                    (((pos + 1) < BOARD_COUNT) &&
375
                     (!board.tile_map[next].value ||
376
                      (board.tile_map[ind].value == board.tile_map[next].value)
377
                      )
378
                     )
379
                    )
380
                return true;
381
        }
382
    }
383
    return false;
384
}
385
 
386
__u32 board_score()
387
{
388
    return board.score;
389
}
390
 
391
void board_update_empty_info()
392
{
393
    board.empty_count = 0;
394
 
395
    __u16 i = 0;
396
    for (i = 0; i < BOARD_MAP_SIZE; i++)
397
    {
398
        if (!board.tile_map[i].value)
399
        {
400
            board.empty_index[board.empty_count] = i;
401
            board.empty_count++;
402
        }
403
    }
404
}
405
 
406
void board_to_tempboard(tile* temp[])
407
{
408
    __u16 ind = 0;
409
    for (ind = 0; ind < BOARD_MAP_SIZE; ind++)
410
    {
411
        tile* bt = &board.tile_map[ind];
412
        if (bt->value)
413
        {
414
            temp[ind] = bt;
415
        }
416
    }
417
}
418
 
419
void board_from_tempboard(tile *temp[], __u8 forward)
420
{
421
    __u16 ind = 0;
422
    if (forward)
423
    {
424
        for (ind = 0; ind < BOARD_MAP_SIZE; ind++)
425
        {
426
            tile* bt = &board.tile_map[ind];
427
            tile* tt = temp[ind];
428
            if (tt)
429
            {
430
                *bt = *tt;
431
                bt->transition = position2cell(board_position(ind));
432
            }
433
            else
434
            {
435
                *bt = null_tile;
436
            }
437
        }
438
    }
439
    else
440
    {
441
        ind = BOARD_MAP_SIZE;
442
        while (ind--)
443
        {
444
            tile* bt = &board.tile_map[ind];
445
            tile* tt = temp[ind];
446
            if (tt)
447
            {
448
                *bt = *tt;
449
                bt->transition = position2cell(board_position(ind));
450
            }
451
            else
452
            {
453
                *bt = null_tile;
454
            }
455
        }
456
    }
457
}
458
 
459
void tempboard_move_tile(tile* temp[], __u16 from, __u16 to)
460
{
461
    temp[to] = temp[from];
462
    temp[to]->animate = true;
463
    temp[from] = 0;
464
}
465
 
466
void tempboard_merge_tile(tile* temp[], __u16 from, __u16 to)
467
{
468
    temp[from]->merged = true;
469
    temp[from]->merged_rect = temp[to]->cell;
470
    tempboard_move_tile(temp,from,to);
471
}
472
 
473
__u32 random_u32(__u32 max)
474
{
475
    return ((rand() * 1.0) / RAND_MAX) * max;
476
}