annotate board.c @ 4:aec74ae4d6e5 version-2

Fix the logic checking whether a generated board is playable
author Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
date Fri, 24 Oct 2014 17:12:12 +0200
parents a9a7ad180c3b
children 4f6bf50dbc4a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
1 /*
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
2 * Copyright (C) 2014 Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
3 *
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
4 * Permission is hereby granted, free of charge, to any person obtaining
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
5 * a copy of this software and associated documentation files (the
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
6 * "Software"), to deal in the Software without restriction, including
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
7 * without limitation the rights to use, copy, modify, merge, publish,
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
8 * distribute, sublicense, and/or sell copies of the Software, and to
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
9 * permit persons to whom the Software is furnished to do so, subject to
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
10 * the following conditions:
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
11 *
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
12 * The above copyright notice and this permission notice shall be included
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
13 * in all copies or substantial portions of the Software.
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
14 *
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
22 */
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
23
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
24 #define _XOPEN_SOURCE 600
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
25
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
26 #include <stdlib.h>
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
27 #include <unistd.h>
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
28 #include <curses.h> /* for OK, ERR */
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
29
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
30 #include "board.h"
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
31 #include "compat.h"
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
32 #include "util.h"
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
33
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
34 struct stack_element {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
35 struct stack_element *next;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
36 int x;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
37 int y;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
38 };
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
39
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
40 struct board_ctx *
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
41 board_create(int height, int width, short colors)
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
42 {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
43 struct board_ctx *board;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
44
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
45 board = rantaiwarna_malloc(sizeof (struct board_ctx));
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
46 board->elements = rantaiwarna_calloc((size_t)(width * height),
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
47 sizeof (short));
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
48 board->seed = (uint32_t)getpid();
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
49 board->height = height;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
50 board->width = width;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
51 board->colors = colors;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
52 board->status = GAME_OVER;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
53 board->score = 0;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
54 if (board_generate(board) == ERR) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
55 board_free(board);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
56 return (NULL);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
57 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
58
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
59 return (board);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
60 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
61
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
62 void
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
63 board_free(struct board_ctx *board)
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
64 {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
65 free(board->elements);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
66 free(board);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
67 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
68
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
69 int
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
70 board_check_status(struct board_ctx *board)
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
71 {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
72 int status = GAME_OVER | GAME_OVER_CLEARED;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
73 int y;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
74 int x;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
75
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
76 for (y = board->height - 1; y >= 0; y--) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
77 for (x = 0; x < board->width; x++) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
78 if (board->elements[y * board->width + x] != 0) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
79 status &= ~GAME_OVER_CLEARED;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
80 if (((y - 1 >= 0) &&
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
81 (board->elements[y * board->width + x] ==
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
82 board->elements[(y - 1) * board->width +
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
83 x])) ||
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
84 ((x + 1 < board->width) &&
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
85 (board->elements[y * board->width + x] ==
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
86 (board->elements[y * board->width + x +
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
87 1])))) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
88 status &= ~GAME_OVER;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
89 goto out;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
90 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
91 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
92 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
93 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
94
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
95 out:
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
96 board->status = status;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
97 return (status);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
98 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
99
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
100 int
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
101 board_generate(struct board_ctx *board)
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
102 {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
103 int i;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
104 int j;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
105
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
106 /* make up to 1000 attempts to create a board that is playable */
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
107 for (i = 0; i < 1000; i++) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
108 for (j = 0; j < board->width * board->height; j++) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
109 board->elements[j] =
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
110 (short)(rantaiwarna_rand(&board->seed) %
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
111 board->colors) + 1;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
112 }
4
aec74ae4d6e5 Fix the logic checking whether a generated board is playable
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents: 0
diff changeset
113 if (!(board_check_status(board) & GAME_OVER)) {
aec74ae4d6e5 Fix the logic checking whether a generated board is playable
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents: 0
diff changeset
114 break;
0
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
115 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
116 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
117
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
118 board->score = 0;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
119
4
aec74ae4d6e5 Fix the logic checking whether a generated board is playable
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents: 0
diff changeset
120 return (!(board->status & GAME_OVER) ? OK : ERR);
0
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
121 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
122
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
123 int
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
124 board_compact(struct board_ctx *board)
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
125 {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
126 int changes = 0;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
127 int x;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
128 int y;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
129 int top;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
130 int left;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
131
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
132 /* close vertical gaps iby moving elements down */
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
133 for (x = 0; x < board->width; x++) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
134 for (y = top = board->height - 1; y >= 0; y--) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
135 if (board->elements[y * board->width + x] != 0) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
136 board->elements[top * board->width + x] =
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
137 board->elements[y * board->width + x];
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
138 top--;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
139 changes++;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
140 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
141 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
142 for (y = top; y >= 0; y--) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
143 board->elements[y * board->width + x] = 0;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
144 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
145 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
146
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
147 /* close column gaps by moving columns to the left */
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
148 for (x = left = 0; x < board->width; x++) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
149 if (board->elements[(board->height - 1) * board->width + x] !=
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
150 0) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
151 if (x > left) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
152 for (y = 0; y < board->height; y++) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
153 board->elements[y * board->width +
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
154 left] = board->elements[y *
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
155 board->width + x];
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
156 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
157 changes++;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
158 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
159 left++;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
160 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
161 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
162 for (x = left; x < board->width; x++) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
163 for (y = 0; y < board->height; y++) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
164 board->elements[y * board->width + x] = 0;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
165 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
166 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
167
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
168 return (changes);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
169 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
170
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
171 int
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
172 board_remove_elements(struct board_ctx *board, int start_y, int start_x)
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
173 {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
174 int removed = 0;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
175 int color;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
176 int x;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
177 int y;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
178 int west;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
179 int east;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
180 int n = 0;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
181 int i;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
182 int save_x;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
183 int save_y;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
184 struct stack_element *stack_start;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
185 struct stack_element *stack_tmp;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
186 struct stack_element *stack_new;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
187
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
188 color = board->elements[start_y * board->width + start_x];
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
189 if (color == 0) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
190 return (0);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
191 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
192
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
193 stack_new = rantaiwarna_malloc(sizeof (struct stack_element));
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
194 stack_new->next = NULL;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
195 stack_new->y = start_y;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
196 stack_new->x = start_x;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
197 stack_start = stack_new;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
198
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
199 while (stack_start != NULL) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
200 x = stack_start->x;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
201 y = stack_start->y;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
202 stack_tmp = stack_start;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
203 stack_start = stack_start->next;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
204 free(stack_tmp);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
205
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
206 if (board->elements[y * board->width + x] != color) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
207 continue;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
208 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
209
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
210 for (west = x; (west - 1 >= 0) &&
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
211 (board->elements[y * board->width + west - 1] == color);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
212 west--);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
213 for (east = x; (east + 1 < board->width) &&
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
214 (board->elements[y * board->width + east + 1] == color);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
215 east++);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
216 for (i = west; i <= east; i++) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
217 /*
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
218 * only really start removing elements if there are
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
219 * more than two adjacent elements of the same color
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
220 */
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
221 n++;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
222 if (n < 2) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
223 save_x = i;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
224 save_y = y;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
225 } else {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
226 if (n == 2) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
227 board->elements[save_y * board->width +
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
228 save_x] = 0;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
229 removed++;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
230 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
231 board->elements[y * board->width + i] = 0;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
232 removed++;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
233 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
234
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
235 if ((y - 1 >= 0) &&
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
236 (board->elements[(y - 1) * board->width + i] ==
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
237 color)) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
238 stack_new = rantaiwarna_malloc(
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
239 sizeof (struct stack_element));
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
240 stack_new->next = stack_start;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
241 stack_new->y = y - 1;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
242 stack_new->x = i;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
243 stack_start = stack_new;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
244 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
245 if ((y + 1 < board->height) &&
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
246 (board->elements[(y + 1) * board->width + i] ==
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
247 color)) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
248 stack_new = rantaiwarna_malloc(
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
249 sizeof (struct stack_element));
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
250 stack_new->next = stack_start;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
251 stack_new->y = y + 1;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
252 stack_new->x = i;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
253 stack_start = stack_new;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
254 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
255 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
256 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
257 if (removed > 0) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
258 board_compact(board);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
259 board->score += (removed - 1) * (removed - 1);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
260 board_check_status(board);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
261 if (board->status & GAME_OVER) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
262 if (board->status & GAME_OVER_CLEARED) {
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
263 board->score += 1000;
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
264 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
265 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
266 }
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
267
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
268 return (removed);
a9a7ad180c3b Initial revision
Guido Berhoerster <guido+rantaiwarna@berhoerster.name>
parents:
diff changeset
269 }