Subversion Repositories Kolibri OS

Rev

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

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