int w, h, minballs, maxballs, nballs, nlasers;
unsigned int *grid; /* (w+2)x(h+2), to allow for laser firing range */
unsigned int *exits; /* one per laser */
- int done; /* user has finished placing his own balls. */
+ bool done; /* user has finished placing his own balls. */
int laserno; /* number of next laser to be fired. */
- int nguesses, reveal, justwrong, nright, nwrong, nmissed;
+ int nguesses, nright, nwrong, nmissed;
+ bool reveal, justwrong;
};
#define GRID(s,x,y) ((s)->grid[(y)*((s)->w+2) + (x)])
};
#endif
-static int range2grid(const game_state *state, int rangeno, int *x, int *y,
- int *direction)
+static bool range2grid(const game_state *state, int rangeno, int *x, int *y,
+ int *direction)
{
if (rangeno < 0)
- return 0;
+ return false;
if (rangeno < state->w) {
/* top row; from (1,0) to (w,0) */
*x = rangeno + 1;
*y = 0;
*direction = DIR_DOWN;
- return 1;
+ return true;
}
rangeno -= state->w;
if (rangeno < state->h) {
*x = state->w+1;
*y = rangeno + 1;
*direction = DIR_LEFT;
- return 1;
+ return true;
}
rangeno -= state->h;
if (rangeno < state->w) {
*x = (state->w - rangeno);
*y = state->h+1;
*direction = DIR_UP;
- return 1;
+ return true;
}
rangeno -= state->w;
if (rangeno < state->h) {
*x = 0;
*y = (state->h - rangeno);
*direction = DIR_RIGHT;
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-static int grid2range(const game_state *state, int x, int y, int *rangeno)
+static bool grid2range(const game_state *state, int x, int y, int *rangeno)
{
int ret, x1 = state->w+1, y1 = state->h+1;
- if (x > 0 && x < x1 && y > 0 && y < y1) return 0; /* in arena */
- if (x < 0 || x > x1 || y < 0 || y > y1) return 0; /* outside grid */
+ if (x > 0 && x < x1 && y > 0 && y < y1) return false; /* in arena */
+ if (x < 0 || x > x1 || y < 0 || y > y1) return false; /* outside grid */
if ((x == 0 || x == x1) && (y == 0 || y == y1))
- return 0; /* one of 4 corners */
+ return false; /* one of 4 corners */
if (y == 0) { /* top line */
ret = x - 1;
}
*rangeno = ret;
debug(("grid2range: (%d,%d) rangeno = %d\n", x, y, ret));
- return 1;
+ return true;
}
static game_state *new_game(midend *me, const game_params *params,
}
sfree(bmp);
- state->done = state->nguesses = state->reveal = state->justwrong =
- state->nright = state->nwrong = state->nmissed = 0;
+ state->done = false;
+ state->justwrong = false;
+ state->reveal = false;
+ state->nguesses = state->nright = state->nwrong = state->nmissed = 0;
state->laserno = 1;
return state;
struct game_ui {
int flash_laserno;
- int errors, newmove;
- int cur_x, cur_y, cur_visible;
+ int errors;
+ bool newmove;
+ int cur_x, cur_y;
+ bool cur_visible;
int flash_laser; /* 0 = never, 1 = always, 2 = if anim. */
};
ui->newmove = false;
ui->cur_x = ui->cur_y = 1;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
ui->flash_laser = 0;
/* Given a position and a direction, check whether we can see a ball in front
* of us, or to our front-left or front-right. */
-static int isball(game_state *state, int gx, int gy, int direction, int lookwhere)
+static bool isball(game_state *state, int gx, int gy, int direction, int lookwhere)
{
debug(("isball, (%d, %d), dir %s, lookwhere %s\n", gx, gy, dirstrs[direction],
lookwhere == LOOK_LEFT ? "LEFT" :
/* if we're off the grid (into the firing range) there's never a ball. */
if (gx < 1 || gy < 1 || gx > state->w || gy > state->h)
- return 0;
+ return false;
if (GRID(state, gx,gy) & BALL_CORRECT)
- return 1;
+ return true;
- return 0;
+ return false;
}
static int fire_laser_internal(game_state *state, int x, int y, int direction)
{
- int unused, lno, tmp;
+ int unused, lno;
+ bool tmp;
tmp = grid2range(state, x, y, &lno);
assert(tmp);
static int laser_exit(game_state *state, int entryno)
{
- int tmp, x, y, direction;
+ int x, y, direction;
+ bool tmp;
tmp = range2grid(state, entryno, &x, &y, &direction);
assert(tmp);
static void fire_laser(game_state *state, int entryno)
{
- int tmp, exitno, x, y, direction;
+ int exitno, x, y, direction;
+ bool tmp;
tmp = range2grid(state, entryno, &x, &y, &direction);
assert(tmp);
* have already guessed). This is required because any layout with >4 balls
* might have multiple valid solutions. Returns non-zero for a 'correct'
* (i.e. consistent) layout. */
-static int check_guesses(game_state *state, int cagey)
+static int check_guesses(game_state *state, bool cagey)
{
game_state *solution, *guesses;
int i, x, y, n, unused, tmp;
+ bool tmpb;
int ret = 0;
if (cagey) {
/* clear out the lasers of solution */
for (i = 0; i < solution->nlasers; i++) {
- tmp = range2grid(solution, i, &x, &y, &unused);
- assert(tmp);
+ tmpb = range2grid(solution, i, &x, &y, &unused);
+ assert(tmpb);
GRID(solution, x, y) = 0;
solution->exits[i] = LASER_EMPTY;
}
/* check each game_state's laser against the other; if any differ, return 0 */
ret = 1;
for (i = 0; i < solution->nlasers; i++) {
- tmp = range2grid(solution, i, &x, &y, &unused);
- assert(tmp);
+ tmpb = range2grid(solution, i, &x, &y, &unused);
+ assert(tmpb);
if (solution->exits[i] != guesses->exits[i]) {
/* If the original state didn't have this shot fired,
else {
/* add a new shot, incrementing state's laser count. */
int ex, ey, newno = state->laserno++;
- tmp = range2grid(state, state->exits[i], &ex, &ey, &unused);
- assert(tmp);
+ tmpb = range2grid(state, state->exits[i], &ex, &ey, &unused);
+ assert(tmpb);
GRID(state, x, y) = newno;
GRID(state, ex, ey) = newno;
}
}
free_game(solution);
free_game(guesses);
- state->reveal = 1;
+ state->reveal = true;
return ret;
}
struct game_drawstate {
int tilesize, crad, rrad, w, h; /* w and h to make macros work... */
unsigned int *grid; /* as the game_state grid */
- int started, reveal;
- int flash_laserno, isflash;
+ bool started, reveal, isflash;
+ int flash_laserno;
};
static char *interpret_move(const game_state *state, game_ui *ui,
if (IS_CURSOR_MOVE(button)) {
int cx = ui->cur_x, cy = ui->cur_y;
- move_cursor(button, &cx, &cy, state->w+2, state->h+2, 0);
+ move_cursor(button, &cx, &cy, state->w+2, state->h+2, false);
if ((cx == 0 && cy == 0 && !CAN_REVEAL(state)) ||
(cx == 0 && cy == state->h+1) ||
(cx == state->w+1 && cy == 0) ||
return NULL; /* disallow moving cursor to corners. */
ui->cur_x = cx;
ui->cur_y = cy;
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
gx = FROMDRAW(x);
gy = FROMDRAW(y);
- ui->cur_visible = 0;
+ ui->cur_visible = false;
wouldflash = 1;
} else if (button == LEFT_RELEASE) {
ui->flash_laser = 0;
ui->flash_laser = 0;
wouldflash = 2;
} else {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
/* Fix up 'button' for the below logic. */
case REVEAL:
if (!CAN_REVEAL(state)) return nullret;
- if (ui->cur_visible == 1) ui->cur_x = ui->cur_y = 1;
+ if (ui->cur_visible) ui->cur_x = ui->cur_y = 1;
sprintf(buf, "R");
break;
ds->w = state->w; ds->h = state->h;
ds->grid = snewn((state->w+2)*(state->h+2), unsigned int);
memset(ds->grid, 0, (state->w+2)*(state->h+2)*sizeof(unsigned int));
- ds->started = ds->reveal = 0;
+ ds->started = false;
+ ds->reveal = false;
ds->flash_laserno = LASER_EMPTY;
- ds->isflash = 0;
+ ds->isflash = false;
return ds;
}
static void draw_arena_tile(drawing *dr, const game_state *gs,
game_drawstate *ds, const game_ui *ui,
- int ax, int ay, int force, int isflash)
+ int ax, int ay, bool force, bool isflash)
{
int gx = ax+1, gy = ay+1;
int gs_tile = GRID(gs, gx, gy), ds_tile = GRID(ds, gx, gy);
static void draw_laser_tile(drawing *dr, const game_state *gs,
game_drawstate *ds, const game_ui *ui,
- int lno, int force)
+ int lno, bool force)
{
int gx, gy, dx, dy, unused;
- int wrong, omitted, reflect, hit, laserval, flash = 0, tmp;
+ int wrong, omitted, laserval;
+ bool tmp, reflect, hit, flash = false;
unsigned int gs_tile, ds_tile, exitno;
tmp = range2grid(gs, lno, &gx, &gy, &unused);
if (exitno == ds->flash_laserno)
gs_tile |= LASER_FLASHED;
}
- if (gs_tile & LASER_FLASHED) flash = 1;
+ if (gs_tile & LASER_FLASHED) flash = true;
gs_tile |= wrong | omitted;
int dir, const game_ui *ui,
float animtime, float flashtime)
{
- int i, x, y, ts = TILE_SIZE, isflash = 0, force = 0;
+ int i, x, y, ts = TILE_SIZE;
+ bool isflash = false, force = false;
if (flashtime > 0) {
int frame = (int)(flashtime / FLASH_FRAME);
draw_update(dr, 0, 0,
TILE_SIZE * (state->w+3), TILE_SIZE * (state->h+3));
- force = 1;
- ds->started = 1;
+ force = true;
+ ds->started = true;
}
- if (isflash != ds->isflash) force = 1;
+ if (isflash != ds->isflash) force = true;
/* draw the arena */
for (x = 0; x < state->w; x++) {
struct game_params {
int w, h, maxb;
int islands, expansion; /* %age of island squares, %age chance of expansion */
- int allowloops, difficulty;
+ bool allowloops;
+ int difficulty;
};
/* general flags used by all structs */
};
struct game_state {
- int w, h, completed, solved, allowloops, maxb;
+ int w, h, maxb;
+ bool completed, solved;
+ bool allowloops;
grid_type *grid;
struct island *islands;
int n_islands, n_islands_alloc;
#define GRIDCOUNT(s,x,y,f) ((GRID(s,x,y) & (f)) ? (INDEX(s,lines,x,y)) : 0)
-#define WITHIN2(x,min,max) (((x) < (min)) ? 0 : (((x) > (max)) ? 0 : 1))
+#define WITHIN2(x,min,max) ((x) >= (min) && (x) < (max))
#define WITHIN(x,min,max) ((min) > (max) ? \
WITHIN2(x,max,min) : WITHIN2(x,min,max))
}
}
-static int island_hasbridge(struct island *is, int direction)
+static bool island_hasbridge(struct island *is, int direction)
{
int x = is->adj.points[direction].x;
int y = is->adj.points[direction].y;
grid_type gline = is->adj.points[direction].dx ? G_LINEH : G_LINEV;
- if (GRID(is->state, x, y) & gline) return 1;
- return 0;
+ if (GRID(is->state, x, y) & gline) return true;
+ return false;
}
static struct island *island_find_connection(struct island *is, int adjpt)
static struct island *island_add(game_state *state, int x, int y, int count)
{
struct island *is;
- int realloced = 0;
+ bool realloced = false;
assert(!(GRID(state,x,y) & G_ISLAND));
GRID(state,x,y) |= G_ISLAND;
state->n_islands_alloc = state->n_islands * 2;
state->islands =
sresize(state->islands, state->n_islands_alloc, struct island);
- realloced = 1;
+ realloced = true;
}
is = &state->islands[state->n_islands-1];
/* n = -1 means 'flip NOLINE flags [and set line to 0].' */
-static void island_join(struct island *i1, struct island *i2, int n, int is_max)
+static void island_join(struct island *i1, struct island *i2, int n, bool is_max)
{
game_state *state = i1->state;
int s, e, x, y;
return c;
}
-static int island_adjspace(struct island *is, int marks, int missing,
+static int island_adjspace(struct island *is, bool marks, int missing,
int direction)
{
int x, y, poss, curr, dx;
/* Counts the number of bridge spaces left around the island;
* expects the possibles to be up-to-date. */
-static int island_countspaces(struct island *is, int marks)
+static int island_countspaces(struct island *is, bool marks)
{
int i, c = 0, missing;
return c;
}
+/* Returns a bridge count rather than a boolean */
static int island_isadj(struct island *is, int direction)
{
int x, y;
}
}
-static int island_impossible(struct island *is, int strict)
+static bool island_impossible(struct island *is, bool strict)
{
int curr = island_countbridges(is), nspc = is->count - curr, nsurrspc;
int i, poss;
if (nspc < 0) {
debug(("island at (%d,%d) impossible because full.\n", is->x, is->y));
- return 1; /* too many bridges */
- } else if ((curr + island_countspaces(is, 0)) < is->count) {
+ return true; /* too many bridges */
+ } else if ((curr + island_countspaces(is, false)) < is->count) {
debug(("island at (%d,%d) impossible because not enough spaces.\n", is->x, is->y));
- return 1; /* impossible to create enough bridges */
+ return true; /* impossible to create enough bridges */
} else if (strict && curr < is->count) {
debug(("island at (%d,%d) impossible because locked.\n", is->x, is->y));
- return 1; /* not enough bridges and island is locked */
+ return true; /* not enough bridges and island is locked */
}
/* Count spaces in surrounding islands. */
if (nsurrspc < nspc) {
debug(("island at (%d,%d) impossible: surr. islands %d spc, need %d.\n",
is->x, is->y, nsurrspc, nspc));
- return 1; /* not enough spaces around surrounding islands to fill this one. */
+ return true; /* not enough spaces around surrounding islands to fill this one. */
}
- return 0;
+ return false;
}
/* --- Game parameter functions --- */
string++;
EATNUM(params->maxb);
}
- params->allowloops = 1;
+ params->allowloops = true;
if (*string == 'L') {
string++;
- params->allowloops = 0;
+ params->allowloops = false;
}
if (*string == 'd') {
string++;
static void map_update_possibles(game_state *state)
{
- int x, y, s, e, bl, i, np, maxb, w = state->w, idx;
+ int x, y, s, e, i, np, maxb, w = state->w, idx;
+ bool bl;
struct island *is_s = NULL, *is_f = NULL;
/* Run down vertical stripes [un]setting possv... */
for (x = 0; x < state->w; x++) {
idx = x;
s = e = -1;
- bl = 0;
+ bl = false;
maxb = state->params.maxb; /* placate optimiser */
/* Unset possible flags until we find an island. */
for (y = 0; y < state->h; y++) {
}
}
s = y+1;
- bl = 0;
+ bl = false;
is_s = is_f;
maxb = is_s->count;
} else {
e = y;
- if (IDX(state,grid,idx) & (G_LINEH|G_NOLINEV)) bl = 1;
+ if (IDX(state,grid,idx) & (G_LINEH|G_NOLINEV)) bl = true;
}
idx += w;
}
for (y = 0; y < state->h; y++) {
idx = y*w;
s = e = -1;
- bl = 0;
+ bl = false;
maxb = state->params.maxb; /* placate optimiser */
for (x = 0; x < state->w; x++) {
is_s = IDX(state, gridi, idx);
}
}
s = x+1;
- bl = 0;
+ bl = false;
is_s = is_f;
maxb = is_s->count;
} else {
e = x;
- if (IDX(state,grid,idx) & (G_LINEV|G_NOLINEH)) bl = 1;
+ if (IDX(state,grid,idx) & (G_LINEV|G_NOLINEH)) bl = true;
}
idx += 1;
}
return -1;
}
-static int map_hasloops(game_state *state, int mark)
+static bool map_hasloops(game_state *state, bool mark)
{
int x, y;
struct findloopstate *fls;
struct bridges_neighbour_ctx ctx;
- int ret;
+ bool ret;
fls = findloop_new_state(state->w * state->h);
ctx.state = state;
}
}
-static int map_group_check(game_state *state, int canon, int warn,
- int *nislands_r)
+static bool map_group_check(game_state *state, int canon, bool warn,
+ int *nislands_r)
{
int *dsf = state->solver->dsf, nislands = 0;
- int x, y, i, allfull = 1;
+ int x, y, i;
+ bool allfull = true;
struct island *is;
for (i = 0; i < state->n_islands; i++) {
GRID(state, is->x, is->y) |= G_SWEEP;
nislands++;
if (island_countbridges(is) != is->count)
- allfull = 0;
+ allfull = false;
}
if (warn && allfull && nislands != state->n_islands) {
/* we're full and this island group isn't the whole set.
return allfull;
}
-static int map_group_full(game_state *state, int *ngroups_r)
+static bool map_group_full(game_state *state, int *ngroups_r)
{
int *dsf = state->solver->dsf, ngroups = 0;
- int i, anyfull = 0;
+ int i;
+ bool anyfull = false;
struct island *is;
/* NB this assumes map_group (or sth else) has cleared G_SWEEP. */
ngroups++;
if (map_group_check(state, dsf_canonify(dsf, DINDEX(is->x,is->y)),
- 1, NULL))
- anyfull = 1;
+ true, NULL))
+ anyfull = true;
}
*ngroups_r = ngroups;
return anyfull;
}
-static int map_check(game_state *state)
+static bool map_check(game_state *state)
{
int ngroups;
/* Check for loops, if necessary. */
if (!state->allowloops) {
- if (map_hasloops(state, 1))
- return 0;
+ if (map_hasloops(state, true))
+ return false;
}
/* Place islands into island groups and check for early
* satisfied-groups. */
map_group(state); /* clears WARN and SWEEP */
if (map_group_full(state, &ngroups)) {
- if (ngroups == 1) return 1;
+ if (ngroups == 1) return true;
}
- return 0;
+ return false;
}
static void map_clear(game_state *state)
}
}
-static void solve_join(struct island *is, int direction, int n, int is_max)
+static void solve_join(struct island *is, int direction, int n, bool is_max)
{
struct island *is_orth;
int d1, d2, *dsf = is->state->solver->dsf;
if (island_hasbridge(is, i)) {
/* already attached; do nothing. */;
} else {
- solve_join(is, i, 1, 0);
+ solve_join(is, i, 1, false);
nadded++;
}
}
/* very like island_countspaces. */
for (i = 0; i < is->adj.npoints; i++) {
- nnew = island_adjspace(is, 1, missing, i);
+ nnew = island_adjspace(is, true, missing, i);
if (nnew) {
ncurr = GRIDCOUNT(is->state,
is->adj.points[i].x, is->adj.points[i].y,
is->adj.points[i].dx ? G_LINEH : G_LINEV);
- solve_join(is, i, nnew + ncurr, 0);
+ solve_join(is, i, nnew + ncurr, false);
nadded += nnew;
}
}
return nadded;
}
-static int solve_island_stage1(struct island *is, int *didsth_r)
+static bool solve_island_stage1(struct island *is, bool *didsth_r)
{
int bridges = island_countbridges(is);
- int nspaces = island_countspaces(is, 1);
+ int nspaces = island_countspaces(is, true);
int nadj = island_countadj(is);
- int didsth = 0;
+ bool didsth = false;
assert(didsth_r);
* another island has become wrong, the puzzle must not have had
* a solution. */
debug(("...island at (%d,%d) is overpopulated!\n", is->x, is->y));
- return 0;
+ return false;
} else if (bridges == is->count) {
/* This island is full. Make sure it's marked (and update
* possibles if we did). */
if (!(GRID(is->state, is->x, is->y) & G_MARK)) {
debug(("...marking island (%d,%d) as full.\n", is->x, is->y));
island_togglemark(is);
- didsth = 1;
+ didsth = true;
}
} else if (GRID(is->state, is->x, is->y) & G_MARK) {
debug(("...island (%d,%d) is marked but unfinished!\n",
is->x, is->y));
- return 0; /* island has been marked unfinished; no solution from here. */
+ return false; /* island has been marked unfinished; no solution from here. */
} else {
/* This is the interesting bit; we try and fill in more information
* about this island. */
if (is->count == bridges + nspaces) {
- if (solve_fill(is) > 0) didsth = 1;
+ if (solve_fill(is) > 0) didsth = true;
} else if (is->count > ((nadj-1) * is->state->maxb)) {
/* must have at least one bridge in each possible direction. */
- if (solve_fillone(is) > 0) didsth = 1;
+ if (solve_fillone(is) > 0) didsth = true;
}
}
if (didsth) {
map_update_possibles(is->state);
- *didsth_r = 1;
+ *didsth_r = true;
}
- return 1;
+ return true;
}
-/* returns non-zero if a new line here would cause a loop. */
-static int solve_island_checkloop(struct island *is, int direction)
+/* returns true if a new line here would cause a loop. */
+static bool solve_island_checkloop(struct island *is, int direction)
{
struct island *is_orth;
int *dsf = is->state->solver->dsf, d1, d2;
game_state *state = is->state;
- if (is->state->allowloops) return 0; /* don't care anyway */
- if (island_hasbridge(is, direction)) return 0; /* already has a bridge */
- if (island_isadj(is, direction) == 0) return 0; /* no adj island */
+ if (is->state->allowloops)
+ return false; /* don't care anyway */
+ if (island_hasbridge(is, direction))
+ return false; /* already has a bridge */
+ if (island_isadj(is, direction) == 0)
+ return false; /* no adj island */
is_orth = INDEX(is->state, gridi,
ISLAND_ORTHX(is,direction),
ISLAND_ORTHY(is,direction));
- if (!is_orth) return 0;
+ if (!is_orth) return false;
d1 = DINDEX(is->x, is->y);
d2 = DINDEX(is_orth->x, is_orth->y);
if (dsf_canonify(dsf, d1) == dsf_canonify(dsf, d2)) {
/* two islands are connected already; don't join them. */
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-static int solve_island_stage2(struct island *is, int *didsth_r)
+static bool solve_island_stage2(struct island *is, bool *didsth_r)
{
- int added = 0, removed = 0, navail = 0, nadj, i;
+ int navail = 0, nadj, i;
+ bool added = false, removed = false;
assert(didsth_r);
if (solve_island_checkloop(is, i)) {
debug(("removing possible loop at (%d,%d) direction %d.\n",
is->x, is->y, i));
- solve_join(is, i, -1, 0);
+ solve_join(is, i, -1, false);
map_update_possibles(is->state);
- removed = 1;
+ removed = true;
} else {
navail += island_isadj(is, i);
/*debug(("stage2: navail for (%d,%d) direction (%d,%d) is %d.\n",
debug(("island at (%d,%d) direction (%d,%d) must have 1 bridge\n",
is->x, is->y,
is->adj.points[i].dx, is->adj.points[i].dy));
- solve_join(is, i, 1, 0);
- added = 1;
+ solve_join(is, i, 1, false);
+ added = true;
/*debug_state(is->state);
debug_possibles(is->state);*/
}
}
}
if (added) map_update_possibles(is->state);
- if (added || removed) *didsth_r = 1;
- return 1;
+ if (added || removed) *didsth_r = true;
+ return true;
}
-static int solve_island_subgroup(struct island *is, int direction)
+static bool solve_island_subgroup(struct island *is, int direction)
{
struct island *is_join;
int nislands, *dsf = is->state->solver->dsf;
/* if is isn't full, return 0. */
if (island_countbridges(is) < is->count) {
debug(("...orig island (%d,%d) not full.\n", is->x, is->y));
- return 0;
+ return false;
}
if (direction >= 0) {
if (island_countbridges(is_join) < is_join->count) {
debug(("...dest island (%d,%d) not full.\n",
is_join->x, is_join->y));
- return 0;
+ return false;
}
}
/* Check group membership for is->dsf; if it's full return 1. */
if (map_group_check(state, dsf_canonify(dsf, DINDEX(is->x,is->y)),
- 0, &nislands)) {
+ false, &nislands)) {
if (nislands < state->n_islands) {
/* we have a full subgroup that isn't the whole set.
* This isn't allowed. */
debug(("island at (%d,%d) makes full subgroup, disallowing.\n",
is->x, is->y));
- return 1;
+ return true;
} else {
debug(("...has finished puzzle.\n"));
}
}
- return 0;
+ return false;
}
-static int solve_island_impossible(game_state *state)
+static bool solve_island_impossible(game_state *state)
{
struct island *is;
int i;
/* If any islands are impossible, return 1. */
for (i = 0; i < state->n_islands; i++) {
is = &state->islands[i];
- if (island_impossible(is, 0)) {
+ if (island_impossible(is, false)) {
debug(("island at (%d,%d) has become impossible, disallowing.\n",
is->x, is->y));
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
/* Bear in mind that this function is really rather inefficient. */
-static int solve_island_stage3(struct island *is, int *didsth_r)
+static bool solve_island_stage3(struct island *is, bool *didsth_r)
{
- int i, n, x, y, missing, spc, curr, maxb, didsth = 0;
+ int i, n, x, y, missing, spc, curr, maxb;
+ bool didsth = false;
int wh = is->state->w * is->state->h;
struct solver_state *ss = is->state->solver;
assert(didsth_r);
missing = is->count - island_countbridges(is);
- if (missing <= 0) return 1;
+ if (missing <= 0) return true;
for (i = 0; i < is->adj.npoints; i++) {
x = is->adj.points[i].x;
y = is->adj.points[i].y;
- spc = island_adjspace(is, 1, missing, i);
+ spc = island_adjspace(is, true, missing, i);
if (spc == 0) continue;
curr = GRIDCOUNT(is->state, x, y,
* it is additive only, and can't be removed from. */
memcpy(ss->tmpdsf, ss->dsf, wh*sizeof(int));
for (n = curr+1; n <= curr+spc; n++) {
- solve_join(is, i, n, 0);
+ solve_join(is, i, n, false);
map_update_possibles(is->state);
if (solve_island_subgroup(is, i) ||
break;
}
}
- solve_join(is, i, curr, 0); /* put back to before. */
+ solve_join(is, i, curr, false); /* put back to before. */
memcpy(ss->dsf, ss->tmpdsf, wh*sizeof(int));
if (maxb != -1) {
/*debug_state(is->state);*/
if (maxb == 0) {
debug(("...adding NOLINE.\n"));
- solve_join(is, i, -1, 0); /* we can't have any bridges here. */
+ solve_join(is, i, -1, false); /* we can't have any bridges here. */
} else {
debug(("...setting maximum\n"));
- solve_join(is, i, maxb, 1);
+ solve_join(is, i, maxb, true);
}
- didsth = 1;
+ didsth = true;
}
map_update_possibles(is->state);
}
* recording the idea that at least one of two edges must have
* a bridge.
*/
- int got = 0;
+ bool got = false;
int before[4];
int j;
- spc = island_adjspace(is, 1, missing, i);
+ spc = island_adjspace(is, true, missing, i);
if (spc == 0) continue;
for (j = 0; j < is->adj.npoints; j++)
memcpy(ss->tmpdsf, ss->dsf, wh*sizeof(int));
for (j = 0; j < is->adj.npoints; j++) {
- spc = island_adjspace(is, 1, missing, j);
+ spc = island_adjspace(is, true, missing, j);
if (spc == 0) continue;
if (j == i) continue;
- solve_join(is, j, before[j] + spc, 0);
+ solve_join(is, j, before[j] + spc, false);
}
map_update_possibles(is->state);
if (solve_island_subgroup(is, -1))
- got = 1;
+ got = true;
for (j = 0; j < is->adj.npoints; j++)
- solve_join(is, j, before[j], 0);
+ solve_join(is, j, before[j], false);
memcpy(ss->dsf, ss->tmpdsf, wh*sizeof(int));
if (got) {
debug(("island at (%d,%d) must connect in direction (%d,%d) to"
" avoid full subgroup.\n",
is->x, is->y, is->adj.points[i].dx, is->adj.points[i].dy));
- solve_join(is, i, 1, 0);
- didsth = 1;
+ solve_join(is, i, 1, false);
+ didsth = true;
}
map_update_possibles(is->state);
}
if (didsth) *didsth_r = didsth;
- return 1;
+ return true;
}
#define CONTINUE_IF_FULL do { \
static int solve_sub(game_state *state, int difficulty, int depth)
{
struct island *is;
- int i, didsth;
+ int i;
while (1) {
- didsth = 0;
+ bool didsth = false;
/* First island iteration: things we can work out by looking at
* properties of the island as a whole. */
ret->gridi = snewn(wh, struct island *);
for (i = 0; i < wh; i++) ret->gridi[i] = NULL;
- ret->solved = ret->completed = 0;
+ ret->solved = false;
+ ret->completed = false;
ret->solver = snew(struct solver_state);
ret->solver->dsf = snew_dsf(wh);
ni_curr++; ni_bad = 0;
join:
- island_join(is, is2, random_upto(rs, tobuild->maxb)+1, 0);
+ island_join(is, is2, random_upto(rs, tobuild->maxb)+1, false);
debug_state(tobuild);
continue;
int dragx_src, dragy_src; /* source; -1 means no drag */
int dragx_dst, dragy_dst; /* src's closest orth island. */
grid_type todraw;
- int dragging, drag_is_noline, nlines;
+ bool dragging, drag_is_noline;
+ int nlines;
- int cur_x, cur_y, cur_visible; /* cursor position */
- int show_hints;
+ int cur_x, cur_y; /* cursor position */
+ bool cur_visible;
+ bool show_hints;
};
static char *ui_cancel_drag(game_ui *ui)
{
ui->dragx_src = ui->dragy_src = -1;
ui->dragx_dst = ui->dragy_dst = -1;
- ui->dragging = 0;
+ ui->dragging = false;
return UI_UPDATE;
}
ui_cancel_drag(ui);
ui->cur_x = state->islands[0].x;
ui->cur_y = state->islands[0].y;
- ui->cur_visible = 0;
- ui->show_hints = 0;
+ ui->cur_visible = false;
+ ui->show_hints = false;
return ui;
}
int w, h;
unsigned long *grid, *newgrid;
int *lv, *lh;
- int started, dragging;
+ bool started, dragging;
};
/*
int gx = FROMCOORD(x), gy = FROMCOORD(y);
char buf[80], *ret;
grid_type ggrid = INGRID(state,gx,gy) ? GRID(state,gx,gy) : 0;
- int shift = button & MOD_SHFT, control = button & MOD_CTRL;
+ bool shift = button & MOD_SHFT, control = button & MOD_CTRL;
button &= ~MOD_MASK;
if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
if (!INGRID(state, gx, gy)) return NULL;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
if (ggrid & G_ISLAND) {
ui->dragx_src = gx;
ui->dragy_src = gy;
if (INGRID(state, ui->dragx_src, ui->dragy_src)
&& (gx != ui->dragx_src || gy != ui->dragy_src)
&& !(GRID(state,ui->dragx_src,ui->dragy_src) & G_MARK)) {
- ui->dragging = 1;
- ui->drag_is_noline = (button == RIGHT_DRAG) ? 1 : 0;
+ ui->dragging = true;
+ ui->drag_is_noline = (button == RIGHT_DRAG);
return update_drag_dst(state, ui, ds, x, y);
} else {
/* cancel a drag when we go back to the starting point */
free_game(solved);
return ret;
} else if (IS_CURSOR_MOVE(button)) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
if (control || shift) {
ui->dragx_src = ui->cur_x;
ui->dragy_src = ui->cur_y;
if (ui->dragging) {
int nx = ui->cur_x, ny = ui->cur_y;
- move_cursor(button, &nx, &ny, state->w, state->h, 0);
+ move_cursor(button, &nx, &ny, state->w, state->h, false);
if (nx == ui->cur_x && ny == ui->cur_y)
return NULL;
update_drag_dst(state, ui, ds,
* before closer islands slightly offset). Swap the order of
* these two loops to change to breadth-first search. */
for (orth = 0; ; orth++) {
- int oingrid = 0;
+ bool oingrid = false;
for (dir = 1; ; dir++) {
- int dingrid = 0;
+ bool dingrid = false;
if (orth > dir) continue; /* only search in cone outwards. */
nx = ui->cur_x + dir*dx + orth*dorthx*orthorder;
ny = ui->cur_y + dir*dy + orth*dorthy*orthorder;
if (INGRID(state, nx, ny)) {
- dingrid = oingrid = 1;
+ dingrid = true;
+ oingrid = true;
if (GRID(state, nx, ny) & G_ISLAND) goto found;
}
nx = ui->cur_x + dir*dx - orth*dorthx*orthorder;
ny = ui->cur_y + dir*dy - orth*dorthy*orthorder;
if (INGRID(state, nx, ny)) {
- dingrid = oingrid = 1;
+ dingrid = true;
+ oingrid = true;
if (GRID(state, nx, ny) & G_ISLAND) goto found;
}
}
} else if (IS_CURSOR_SELECT(button)) {
if (!ui->cur_visible) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
if (ui->dragging || button == CURSOR_SELECT2) {
} else {
grid_type v = GRID(state, ui->cur_x, ui->cur_y);
if (v & G_ISLAND) {
- ui->dragging = 1;
+ ui->dragging = true;
ui->dragx_src = ui->cur_x;
ui->dragy_src = ui->cur_y;
ui->dragx_dst = ui->dragy_dst = -1;
- ui->drag_is_noline = (button == CURSOR_SELECT2) ? 1 : 0;
+ ui->drag_is_noline = (button == CURSOR_SELECT2);
return UI_UPDATE;
}
}
number = 10 + button - 'A';
if (!ui->cur_visible) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
} else
return NULL;
} else if (button == 'g' || button == 'G') {
- ui->show_hints = 1 - ui->show_hints;
+ ui->show_hints = !ui->show_hints;
return UI_UPDATE;
}
is2 = INDEX(ret, gridi, x2, y2);
if (!is1 || !is2) goto badmove;
if (nl < 0 || nl > state->maxb) goto badmove;
- island_join(is1, is2, nl, 0);
+ island_join(is1, is2, nl, false);
} else if (c == 'N') {
if (sscanf(move, "%d,%d,%d,%d%n",
&x1, &y1, &x2, &y2, &n) != 4)
is1 = INDEX(ret, gridi, x1, y1);
is2 = INDEX(ret, gridi, x2, y2);
if (!is1 || !is2) goto badmove;
- island_join(is1, is2, -1, 0);
+ island_join(is1, is2, -1, false);
} else if (c == 'M') {
if (sscanf(move, "%d,%d%n",
&x1, &y1, &n) != 2)
map_update_possibles(ret);
if (map_check(ret)) {
debug(("Game completed.\n"));
- ret->completed = 1;
+ ret->completed = true;
}
return ret;
ds->tilesize = 0;
ds->w = state->w;
ds->h = state->h;
- ds->started = 0;
- ds->dragging = 0;
+ ds->started = false;
+ ds->dragging = false;
ds->grid = snewn(wh, unsigned long);
for (i = 0; i < wh; i++)
ds->grid[i] = ~0UL;
#define OFFSET(thing) ((TILE_SIZE/2) - ((thing)/2))
-static int between_island(const game_state *state, int sx, int sy,
- int dx, int dy)
+static bool between_island(const game_state *state, int sx, int sy,
+ int dx, int dy)
{
int x = sx - dx, y = sy - dy;
if (GRID(state, x, y) & G_ISLAND) goto found;
x -= dx; y -= dy;
}
- return 0;
+ return false;
found:
x = sx + dx, y = sy + dy;
while (INGRID(state, x, y)) {
- if (GRID(state, x, y) & G_ISLAND) return 1;
+ if (GRID(state, x, y) & G_ISLAND) return true;
x += dx; y += dy;
}
- return 0;
+ return false;
}
static void lines_lvlh(const game_state *state, const game_ui *ui,
float animtime, float flashtime)
{
int x, y, lv, lh;
- grid_type v, flash = 0;
+ grid_type v;
+ bool flash = false;
struct island *is, *is_drag_src = NULL, *is_drag_dst = NULL;
if (flashtime) {
draw_update(dr, 0, 0,
TILE_SIZE * ds->w + 2 * BORDER,
TILE_SIZE * ds->h + 2 * BORDER);
- ds->started = 1;
+ ds->started = true;
}
if (ui->dragx_src != -1 && ui->dragy_src != -1) {
- ds->dragging = 1;
+ ds->dragging = true;
is_drag_src = INDEX(state, gridi, ui->dragx_src, ui->dragy_src);
assert(is_drag_src);
if (ui->dragx_dst != -1 && ui->dragy_dst != -1) {
assert(is_drag_dst);
}
} else
- ds->dragging = 0;
+ ds->dragging = false;
/*
* Set up ds->newgrid with the current grid contents.
INDEX(ds,newgrid,x,y+1) |= idata << D_L_ISLAND_SHIFT_U;
} else {
unsigned long hdata, vdata;
- int selh = false, selv = false;
+ bool selh = false, selv = false;
/*
* A line (non-island) square. Compute the drawing
int npoints;
float points[8]; /* maximum */
int directions[8]; /* bit masks showing point pairs */
- int flip;
+ bool flip;
int tetra_class;
};
int dpkey[2]; /* key-point indices into polyhedron */
int previous;
float angle;
- int completed;
+ int completed; /* stores move count at completion */
int movecount;
};
{
struct grid_data data;
int i, j, k, m, area, facesperclass;
- int *flags;
+ bool *flags;
char *desc, *p;
/*
* So now we know how many faces to allocate in each class. Get
* on with it.
*/
- flags = snewn(area, int);
+ flags = snewn(area, bool);
for (i = 0; i < area; i++)
flags[i] = false;
return best;
}
-static int align_poly(const struct solid *solid, struct grid_square *sq,
- int *pkey)
+static bool align_poly(const struct solid *solid, struct grid_square *sq,
+ int *pkey)
{
float zmin;
int i, j;
return true;
}
-static void flip_poly(struct solid *solid, int flip)
+static void flip_poly(struct solid *solid, bool flip)
{
int i;
}
}
-static struct solid *transform_poly(const struct solid *solid, int flip,
+static struct solid *transform_poly(const struct solid *solid, bool flip,
int key0, int key1, float angle)
{
struct solid *ret = snew(struct solid);
*/
{
int pkey[4];
- int ret;
+ bool ret;
ret = align_poly(state->solid, &state->grid->squares[state->current], pkey);
assert(ret);
*/
{
int all_pkey[4];
- int success;
+ bool success;
if (from->solid->order == 4 && direction == UP)
angle = -angle; /* HACK */
*/
{
int pkey[4];
- int success;
+ bool success;
success = align_poly(ret->solid, &ret->grid->squares[ret->current], pkey);
assert(success);
* (This only works _because_ we've ensured the omino is simply
* connected.)
*/
-static int addremcommon(int w, int h, int x, int y, int *own, int val)
+static bool addremcommon(int w, int h, int x, int y, int *own, int val)
{
int neighbours[8];
int dir, count;
for (dir = 0; dir < 8; dir++) {
int next = (dir + 1) & 7;
- int gotthis = (neighbours[dir] == val);
- int gotnext = (neighbours[next] == val);
+ bool gotthis = (neighbours[dir] == val);
+ bool gotnext = (neighbours[next] == val);
if (gotthis != gotnext)
count++;
*/
static int *divvy_internal(int w, int h, int k, random_state *rs)
{
- int *order, *queue, *tmp, *own, *sizes, *addable, *removable, *retdsf;
+ int *order, *queue, *tmp, *own, *sizes, *addable, *retdsf;
+ bool *removable;
int wh = w*h;
int i, j, n, x, y, qhead, qtail;
sizes = snewn(n, int);
queue = snewn(n, int);
addable = snewn(wh*4, int);
- removable = snewn(wh, int);
+ removable = snewn(wh, bool);
/*
* Permute the grid squares into a random order, which will be
struct game_params {
int n;
- int unique;
+ bool unique;
};
struct game_numbers {
struct game_numbers *numbers;
int *grid;
unsigned short *edges; /* h x w */
- int completed, cheated;
+ bool completed, cheated;
};
static game_params *default_params(void)
#endif
while (1) {
- int done_something = false;
+ bool done_something = false;
/*
* For each domino, look at its possible placements, and
state->numbers->numbers[i] = j;
}
- state->completed = state->cheated = false;
+ state->completed = false;
+ state->cheated = false;
return state;
}
}
struct game_ui {
- int cur_x, cur_y, cur_visible, highlight_1, highlight_2;
+ int cur_x, cur_y, highlight_1, highlight_2;
+ bool cur_visible;
};
static game_ui *new_ui(const game_state *state)
{
game_ui *ui = snew(game_ui);
ui->cur_x = ui->cur_y = 0;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
ui->highlight_1 = ui->highlight_2 = -1;
return ui;
}
const game_state *newstate)
{
if (!oldstate->completed && newstate->completed)
- ui->cur_visible = 0;
+ ui->cur_visible = false;
}
#define PREFERRED_TILESIZE 32
#define FROMCOORD(x) ( ((x) - BORDER + TILESIZE) / TILESIZE - 1 )
struct game_drawstate {
- int started;
+ bool started;
int w, h, tilesize;
unsigned long *visible;
};
(state->grid[d1] != d1 || state->grid[d2] != d2))
return NULL;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
sprintf(buf, "%c%d,%d", (int)(button == RIGHT_BUTTON ? 'E' : 'D'), d1, d2);
return dupstr(buf);
} else if (IS_CURSOR_MOVE(button)) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
- move_cursor(button, &ui->cur_x, &ui->cur_y, 2*w-1, 2*h-1, 0);
+ move_cursor(button, &ui->cur_x, &ui->cur_y, 2*w-1, 2*h-1, false);
return UI_UPDATE;
} else if (IS_CURSOR_SELECT(button)) {
*/
if (!ret->completed) {
int i, ok = 0;
- unsigned char *used = snewn(TRI(n+1), unsigned char);
+ bool *used = snewn(TRI(n+1), bool);
memset(used, 0, TRI(n+1));
for (i = 0; i < wh; i++)
assert(di >= 0 && di < TRI(n+1));
if (!used[di]) {
- used[di] = 1;
+ used[di] = true;
ok++;
}
}
index = start_index;
while (index != canonical_index) {
int nextindex = dsf[index] >> 2;
- int nextinverse = inverse ^ (dsf[index] & 1);
+ bool nextinverse = inverse ^ (dsf[index] & 1);
dsf[index] = (canonical_index << 2) | inverse;
inverse = nextinverse;
index = nextindex;
}
- assert(inverse == 0);
+ assert(!inverse);
/* fprintf(stderr, "Return %2d\n", index); */
if (v1 == v2)
assert(!inverse);
else {
- assert(inverse == 0 || inverse == 1);
/*
* We always make the smaller of v1 and v2 the new canonical
* element. This ensures that the canonical element of any
v2 = v3;
}
dsf[v1] += (dsf[v2] >> 2) << 2;
- dsf[v2] = (v1 << 2) | !!inverse;
+ dsf[v2] = (v1 << 2) | inverse;
}
v2 = edsf_canonify(dsf, v2, &i2);
extern void js_select_preset(int n);
extern void js_get_date_64(unsigned *p);
extern void js_update_permalinks(const char *desc, const char *seed);
-extern void js_enable_undo_redo(int undo, int redo);
+extern void js_enable_undo_redo(bool undo, bool redo);
extern void js_activate_timer();
extern void js_deactivate_timer();
extern void js_canvas_start_draw(void);
extern void js_dialog_string(int i, const char *title, const char *initvalue);
extern void js_dialog_choices(int i, const char *title, const char *choicelist,
int initvalue);
-extern void js_dialog_boolean(int i, const char *title, int initvalue);
+extern void js_dialog_boolean(int i, const char *title, bool initvalue);
extern void js_dialog_launch(void);
extern void js_dialog_cleanup(void);
extern void js_focus_canvas(void);
/* ----------------------------------------------------------------------
* Timing functions.
*/
-int timer_active = false;
+bool timer_active = false;
void deactivate_timer(frontend *fe)
{
js_deactivate_timer();
* Keyboard handler called from JS.
*/
void key(int keycode, int charcode, const char *key, const char *chr,
- int shift, int ctrl)
+ bool shift, bool ctrl)
{
int keyevent = -1;
*/
static game_params **presets;
static int npresets;
-int have_presets_dropdown;
+bool have_presets_dropdown;
void populate_js_preset_menu(int menuid, struct preset_menu *menu)
{
* or false respectively, in those cases. We terminate the dialog box,
* unless the user selected an invalid combination of parameters.
*/
-static void cfg_end(int use_results)
+static void cfg_end(bool use_results)
{
if (use_results) {
/*
int w, h, n;
int *tiles;
int gap_pos;
- int completed;
- int used_solve; /* used to suppress completion flash */
+ int completed; /* move count at time of completion */
+ bool used_solve; /* used to suppress completion flash */
int movecount;
};
{
int gap, n, i, x;
int x1, x2, p1, p2, parity;
- int *tiles, *used;
+ int *tiles;
+ bool *used;
char *ret;
int retlen;
n = params->w * params->h;
tiles = snewn(n, int);
- used = snewn(n, int);
+ used = snewn(n, bool);
for (i = 0; i < n; i++) {
tiles[i] = -1;
const char *p;
const char *err;
int i, area;
- int *used;
+ bool *used;
area = params->w * params->h;
p = desc;
err = NULL;
- used = snewn(area, int);
+ used = snewn(area, bool);
for (i = 0; i < area; i++)
used[i] = false;
}
struct game_drawstate {
- int started;
+ bool started;
int w, h, bgcolour;
int *tiles;
int tilesize;
{
const int to_tile_x = (gx < nx ? +1 : -1);
const int to_goal_x = (gx < tx ? +1 : -1);
- const int gap_x_on_goal_side = ((nx-tx) * (nx-gx) > 0);
+ const bool gap_x_on_goal_side = ((nx-tx) * (nx-gx) > 0);
assert (nx != tx || ny != ty); /* not already in place */
assert (nx != gx || ny != gy); /* not placing the gap */
*dx = to_tile_x;
}
-static int compute_hint(const game_state *state, int *out_x, int *out_y)
+static bool compute_hint(const game_state *state, int *out_x, int *out_y)
{
/* The overall solving process is this:
* 1. Find the next piece to be put in its place
game_state *state;
char *id = NULL, *desc;
const char *err;
- int grade = false;
+ bool grade = false;
char *progname = argv[0];
char buf[80];
- int limit, x, y, solvable;
+ int limit, x, y;
+ bool solvable;
while (--argc > 0) {
char *p = *++argv;
#include "puzzles.h"
-static unsigned char verbose;
+static bool verbose;
static void printv(const char *fmt, ...) {
#ifndef PALM
struct game_state {
int *board;
struct shared_state *shared;
- int completed, cheated;
+ bool completed, cheated;
};
static const struct game_params filling_defaults[3] = {
#define SENTINEL sz
-static int mark_region(int *board, int w, int h, int i, int n, int m) {
+static bool mark_region(int *board, int w, int h, int i, int n, int m) {
int j;
board[i] = -1;
{
const int sz = w * h;
const int maxsize = min(max(max(w, h), 3), 9);
- int i, j, k, change;
+ int i, j, k;
+ bool change;
do {
change = false;
for (i = 0; i < sz; ++i) {
for (j = 0; j < 4; ++j, board[i] = 1) {
const int x = (i % w) + dx[j], y = (i / w) + dy[j];
- int oldsize, newsize, ok, ii = w*y + x;
+ int oldsize, newsize, ii = w*y + x;
+ bool ok;
+
if (x < 0 || x >= w || y < 0 || y >= h) continue;
if (board[ii] == maxsize) continue;
/* Note that if 1 in {w, h} then it's impossible to have a region
* of size > w*h, so the special case only affects w=h=2. */
- int i, change, *dsf;
+ int i, *dsf;
+ bool change;
assert(w >= 1);
assert(h >= 1);
for (i = 0; i < sz; ++i) {
const int square = dsf_canonify(dsf, board[i]);
const int size = dsf_size(dsf, square);
- int merge = SENTINEL, min = maxsize - size + 1, error = false;
+ int merge = SENTINEL, min = maxsize - size + 1;
+ bool error = false;
int neighbour, neighbour_size, j;
for (j = 0; j < 4; ++j) {
}
}
-static int check_capacity(int *board, int w, int h, int i) {
+static bool check_capacity(int *board, int w, int h, int i) {
int n = board[i];
flood_count(board, w, h, i, board[i], &n);
clear_count(board, w * h);
else filled_square(s, w, h, i);
}
-static int learn_expand_or_one(struct solver_state *s, int w, int h) {
+static bool learn_expand_or_one(struct solver_state *s, int w, int h) {
const int sz = w * h;
int i;
- int learn = false;
+ bool learn = false;
assert(s);
for (i = 0; i < sz; ++i) {
int j;
- int one = true;
+ bool one = true;
if (s->board[i] != EMPTY) continue;
return learn;
}
-static int learn_blocked_expansion(struct solver_state *s, int w, int h) {
+static bool learn_blocked_expansion(struct solver_state *s, int w, int h) {
const int sz = w * h;
int i;
- int learn = false;
+ bool learn = false;
assert(s);
/* for every connected component */
return learn;
}
-static int learn_critical_square(struct solver_state *s, int w, int h) {
+static bool learn_critical_square(struct solver_state *s, int w, int h) {
const int sz = w * h;
int i;
- int learn = false;
+ bool learn = false;
assert(s);
/* for each connected component */
}
#endif
-static int learn_bitmap_deductions(struct solver_state *s, int w, int h)
+static bool learn_bitmap_deductions(struct solver_state *s, int w, int h)
{
const int sz = w * h;
int *bm = s->bm;
int *dsf = s->bmdsf;
int *minsize = s->bmminsize;
int x, y, i, j, n;
- int learn = false;
+ bool learn = false;
/*
* This function does deductions based on building up a bitmap
return learn;
}
-static int solver(const int *orig, int w, int h, char **solution) {
+static bool solver(const int *orig, int w, int h, char **solution) {
const int sz = w * h;
struct solver_state ss;
int sz = params->w * params->h;
int i;
- state->cheated = state->completed = false;
+ state->cheated = false;
+ state->completed = false;
state->shared = snew(struct shared_state);
state->shared->refcnt = 1;
state->shared->params = *params; /* struct copy */
*****************************************************************************/
struct game_ui {
- int *sel; /* w*h highlighted squares, or NULL */
- int cur_x, cur_y, cur_visible, keydragging;
+ bool *sel; /* w*h highlighted squares, or NULL */
+ int cur_x, cur_y;
+ bool cur_visible, keydragging;
};
static game_ui *new_ui(const game_state *state)
game_ui *ui = snew(game_ui);
ui->sel = NULL;
- ui->cur_x = ui->cur_y = ui->cur_visible = ui->keydragging = 0;
+ ui->cur_x = ui->cur_y = 0;
+ ui->cur_visible = false;
+ ui->keydragging = false;
return ui;
}
struct game_drawstate {
struct game_params params;
int tilesize;
- int started;
+ bool started;
int *v, *flags;
int *dsf_scratch, *border_scratch;
};
}
if (tx >= 0 && tx < w && ty >= 0 && ty < h) {
if (!ui->sel) {
- ui->sel = snewn(w*h, int);
- memset(ui->sel, 0, w*h*sizeof(int));
+ ui->sel = snewn(w*h, bool);
+ memset(ui->sel, 0, w*h*sizeof(bool));
}
if (!state->shared->clues[w*ty+tx])
- ui->sel[w*ty+tx] = 1;
+ ui->sel[w*ty+tx] = true;
}
- ui->cur_visible = 0;
+ ui->cur_visible = false;
return UI_UPDATE;
}
if (IS_CURSOR_MOVE(button)) {
- ui->cur_visible = 1;
- move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, 0);
+ ui->cur_visible = true;
+ move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, false);
if (ui->keydragging) goto select_square;
return UI_UPDATE;
}
if (button == CURSOR_SELECT) {
if (!ui->cur_visible) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
ui->keydragging = !ui->keydragging;
select_square:
if (!ui->sel) {
- ui->sel = snewn(w*h, int);
- memset(ui->sel, 0, w*h*sizeof(int));
+ ui->sel = snewn(w*h, bool);
+ memset(ui->sel, 0, w*h*sizeof(bool));
}
if (!state->shared->clues[w*ui->cur_y + ui->cur_x])
- ui->sel[w*ui->cur_y + ui->cur_x] = 1;
+ ui->sel[w*ui->cur_y + ui->cur_x] = true;
return UI_UPDATE;
}
if (button == CURSOR_SELECT2) {
if (!ui->cur_visible) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
if (!ui->sel) {
- ui->sel = snewn(w*h, int);
- memset(ui->sel, 0, w*h*sizeof(int));
+ ui->sel = snewn(w*h, bool);
+ memset(ui->sel, 0, w*h*sizeof(bool));
}
ui->keydragging = false;
if (!state->shared->clues[w*ui->cur_y + ui->cur_x])
int i;
ds->tilesize = PREFERRED_TILE_SIZE;
- ds->started = 0;
+ ds->started = false;
ds->params = state->shared->params;
ds->v = snewn(ds->params.w * ds->params.h, int);
ds->flags = snewn(ds->params.w * ds->params.h, int);
TILE_SIZE);
}
-static void draw_grid(drawing *dr, game_drawstate *ds, const game_state *state,
- const game_ui *ui, int flashy, int borders, int shading)
+static void draw_grid(
+ drawing *dr, game_drawstate *ds, const game_state *state,
+ const game_ui *ui, bool flashy, bool borders, bool shading)
{
const int w = state->shared->params.w;
const int h = state->shared->params.h;
int v1, s1, v2, s2;
for (dx = 0; dx <= 1; dx++) {
- int border = false;
+ bool border = false;
dy = 1 - dx;
const int w = state->shared->params.w;
const int h = state->shared->params.h;
- const int flashy =
+ const bool flashy =
flashtime > 0 &&
(flashtime <= FLASH_TIME/3 || flashtime >= FLASH_TIME*2/3);
{
const int w = state->shared->params.w;
const int h = state->shared->params.h;
- int c, i, borders;
+ int c, i;
+ bool borders;
/* Ick: fake up `ds->tilesize' for macro expansion purposes */
game_drawstate *ds = game_new_drawstate(dr, state);
#include "puzzles.h"
struct findloopstate {
- int parent, child, sibling, visited;
+ int parent, child, sibling;
+ bool visited;
int index, minindex, maxindex;
int minreachable, maxreachable;
int bridge;
struct game_state {
int w, h;
- int moves, completed, cheated, hints_active;
+ int moves;
+ bool completed, cheated, hints_active;
unsigned char *grid; /* array of w*h */
struct matrix *matrix;
};
#undef DOWN
struct game_ui {
- int cx, cy, cdraw;
+ int cx, cy;
+ bool cdraw;
};
static game_ui *new_ui(const game_state *state)
{
game_ui *ui = snew(game_ui);
- ui->cx = ui->cy = ui->cdraw = 0;
+ ui->cx = ui->cy = 0;
+ ui->cdraw = false;
return ui;
}
}
struct game_drawstate {
- int w, h, started;
+ int w, h;
+ bool started;
unsigned char *tiles;
int tilesize;
};
int tx, ty;
if (button == LEFT_BUTTON) {
tx = FROMCOORD(x), ty = FROMCOORD(y);
- ui->cdraw = 0;
+ ui->cdraw = false;
} else {
tx = ui->cx; ty = ui->cy;
- ui->cdraw = 1;
+ ui->cdraw = true;
}
nullret = UI_UPDATE;
* will have at least one square do nothing whatsoever.
* If so, we avoid encoding a move at all.
*/
- int i = ty*w+tx, j, makemove = false;
+ int i = ty*w+tx, j;
+ bool makemove = false;
for (j = 0; j < wh; j++) {
if (state->matrix->matrix[i*wh+j])
makemove = true;
ui->cx += dx; ui->cy += dy;
ui->cx = min(max(ui->cx, 0), state->w - 1);
ui->cy = min(max(ui->cy, 0), state->h - 1);
- ui->cdraw = 1;
+ ui->cdraw = true;
nullret = UI_UPDATE;
}
} else if (move[0] == 'M' &&
sscanf(move+1, "%d,%d", &x, &y) == 2 &&
x >= 0 && x < w && y >= 0 && y < h) {
- int i, j, done;
+ int i, j;
+ bool done;
ret = dup_game(from);
}
static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state,
- int x, int y, int tile, int anim, float animtime)
+ int x, int y, int tile, bool anim, float animtime)
{
int w = ds->w, h = ds->h, wh = w * h;
int bx = x * TILE_SIZE + BORDER, by = y * TILE_SIZE + BORDER;
struct game_state {
int w, h, colours;
int moves, movelimit;
- int complete;
+ bool complete;
char *grid;
- int cheated;
+ bool cheated;
int solnpos;
soln *soln;
};
/*
* Detect a completed grid.
*/
-static int completed(int w, int h, char *grid)
+static bool completed(int w, int h, char *grid)
{
int wh = w*h;
int i;
}
struct game_ui {
- int cursor_visible;
+ bool cursor_visible;
int cx, cy;
enum { VICTORY, DEFEAT } flash_type;
};
}
struct game_drawstate {
- int started;
+ bool started;
int tilesize;
int *grid;
};
TILESIZE * w + 2 * SEP_WIDTH, TILESIZE * h + 2 * SEP_WIDTH,
COL_SEPARATOR);
- ds->started = 1;
+ ds->started = true;
}
if (flashtime > 0) {
#ifdef DEBUGGING
#define solvep debug
#else
-int solver_show_working;
+bool solver_show_working;
#define solvep(x) do { if (solver_show_working) { printf x; } } while(0)
#endif
int w, h; /* size from params */
int sx, sy; /* allocated size, (2x-1)*(2y-1) */
space *grid;
- int completed, used_solve;
+ bool completed, used_solve;
int ndots;
space **dots;
or -1 if stale. */
};
-static int check_complete(const game_state *state, int *dsf, int *colours);
+static bool check_complete(const game_state *state, int *dsf, int *colours);
static int solver_state(game_state *state, int maxdiff);
static int solver_obvious(game_state *state);
static int solver_obvious_dot(game_state *state, space *dot);
static int foreach_sub(game_state *state, space_cb cb, unsigned int f,
void *ctx, int startx, int starty)
{
- int x, y, progress = 0, impossible = 0, ret;
+ int x, y, ret;
+ bool progress = false, impossible = false;
space *sp;
for (y = starty; y < state->sy; y += 2) {
ret = cb(state, sp, ctx);
if (ret == -1) {
if (f & IMPOSSIBLE_QUITS) return -1;
- impossible = -1;
+ impossible = true;
} else if (ret == 1) {
- progress = 1;
+ progress = true;
}
sp += 2;
}
}
- return impossible ? -1 : progress;
+ return impossible ? -1 : progress ? 1 : 0;
}
static int foreach_tile(game_state *state, space_cb cb, unsigned int f,
return space_opposite_dot(state, sp, dot);
}
-static int dotfortile(game_state *state, space *tile, space *dot)
+static bool dotfortile(game_state *state, space *tile, space *dot)
{
space *tile_opp = space_opposite_dot(state, tile, dot);
- if (!tile_opp) return 0; /* opposite would be off grid */
+ if (!tile_opp) return false; /* opposite would be off grid */
if (tile_opp->flags & F_TILE_ASSOC &&
(tile_opp->dotx != dot->x || tile_opp->doty != dot->y))
- return 0; /* opposite already associated with diff. dot */
- return 1;
+ return false; /* opposite already associated with diff. dot */
+ return true;
}
static void adjacencies(game_state *state, space *sp, space **a1s, space **a2s)
}
}
-static int outline_tile_fordot(game_state *state, space *tile, int mark)
+static bool outline_tile_fordot(game_state *state, space *tile, bool mark)
{
space *tadj[4], *eadj[4];
- int i, didsth = 0, edge, same;
+ int i;
+ bool didsth = false, edge, same;
assert(tile->type == s_tile);
adjacencies(state, tile, eadj, tadj);
for (i = 0; i < 4; i++) {
if (!eadj[i]) continue;
- edge = (eadj[i]->flags & F_EDGE_SET) ? 1 : 0;
+ edge = eadj[i]->flags & F_EDGE_SET;
if (tadj[i]) {
if (!(tile->flags & F_TILE_ASSOC))
- same = (tadj[i]->flags & F_TILE_ASSOC) ? 0 : 1;
+ same = !(tadj[i]->flags & F_TILE_ASSOC);
else
same = ((tadj[i]->flags & F_TILE_ASSOC) &&
tile->dotx == tadj[i]->dotx &&
- tile->doty == tadj[i]->doty) ? 1 : 0;
+ tile->doty == tadj[i]->doty);
} else
- same = 0;
+ same = false;
if (!edge && !same) {
if (mark) eadj[i]->flags |= F_EDGE_SET;
- didsth = 1;
+ didsth = true;
} else if (edge && same) {
if (mark) eadj[i]->flags &= ~F_EDGE_SET;
- didsth = 1;
+ didsth = true;
}
}
return didsth;
/* Returns a move string for use by 'solve', including the initial
* 'S' if issolve is true. */
static char *diff_game(const game_state *src, const game_state *dest,
- int issolve)
+ bool issolve)
{
int movelen = 0, movesize = 256, x, y, len;
char *move = snewn(movesize, char), buf[80];
return move;
}
-/* Returns 1 if a dot here would not be too close to any other dots
+/* Returns true if a dot here would not be too close to any other dots
* (and would avoid other game furniture). */
-static int dot_is_possible(game_state *state, space *sp, int allow_assoc)
+static bool dot_is_possible(game_state *state, space *sp, bool allow_assoc)
{
int bx = 0, by = 0, dx, dy;
space *adj;
if (col < 0)
col = c;
if (c != col)
- return 0; /* colour mismatch */
+ return false; /* colour mismatch */
}
}
#endif
if (!allow_assoc && (adj->flags & F_TILE_ASSOC))
- return 0;
+ return false;
if (dx != 0 || dy != 0) {
/* Other than our own square, no dots nearby. */
if (adj->flags & (F_DOT))
- return 0;
+ return false;
}
/* We don't want edges within our rectangle
* (but don't care about edges on the edge) */
if (abs(dx) < bx && abs(dy) < by &&
adj->flags & F_EDGE_SET)
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
/* ----------------------------------------------------------
state->sx = (w*2)+1;
state->sy = (h*2)+1;
state->grid = snewn(state->sx * state->sy, space);
- state->completed = state->used_solve = 0;
+ state->completed = false;
+ state->used_solve = false;
for (x = 0; x < state->sx; x++) {
for (y = 0; y < state->sy; y++) {
}
}
-static void clear_game(game_state *state, int cleardots)
+static void clear_game(game_state *state, bool cleardots)
{
int x, y;
* extra spaces (by checking for empty spaces on the far side), and then
* see if we can move the dot to shift the CoG to include the new spaces.
*/
-static int dot_expand_or_move(game_state *state, space *dot,
- space **toadd, int nadd)
+static bool dot_expand_or_move(game_state *state, space *dot,
+ space **toadd, int nadd)
{
space *tileopp;
int i, ret, nnew, cx, cy;
for (i = 0; i < nadd; i++) {
if (!(picture[(toadd[i]->y/2) * state->w + (toadd[i]->x/2)]) ^
!(dot->flags & F_DOT_BLACK))
- return 0;
+ return false;
}
}
#endif
dot->x, dot->y));
dbg_state(state);
}
- return 1;
+ return true;
noexpand:
/* Otherwise, try to move dot so as to encompass given spaces: */
if ((cx % nnew) != 0 || (cy % nnew) != 0) {
debug(("Unable to move dot %d,%d, CoG not whole number.\n",
dot->x, dot->y));
- return 0;
+ return false;
}
cx /= nnew; cy /= nnew;
if (ret == -1) {
debug(("Unable to move dot %d,%d, new dot not symmetrical.\n",
dot->x, dot->y));
- return 0;
+ return false;
}
/* Also check whether all spaces we're adding would have a good
* opposite wrt the new dot. */
if (!tileopp) {
debug(("Unable to move dot %d,%d, new dot not symmetrical.\n",
dot->x, dot->y));
- return 0;
+ return false;
}
#ifdef STANDALONE_PICTURE_GENERATOR
if (picture) {
if (!(picture[(tileopp->y/2) * state->w + (tileopp->x/2)]) ^
!(dot->flags & F_DOT_BLACK))
- return 0;
+ return false;
}
#endif
}
assert(ret == 1);
dbg_state(state);
- return 1;
+ return true;
}
/* Hard-code to a max. of 2x2 squares, for speed (less malloc) */
#define MAX_TILE_PERC 20
-static int generate_try_block(game_state *state, random_state *rs,
- int x1, int y1, int x2, int y2)
+static bool generate_try_block(game_state *state, random_state *rs,
+ int x1, int y1, int x2, int y2)
{
int x, y, nadd = 0, nout = 0, i, maxsz;
space *sp, *toadd[MAX_TOADD], *outside[MAX_OUTSIDE], *dot;
- if (!INGRID(state, x1, y1) || !INGRID(state, x2, y2)) return 0;
+ if (!INGRID(state, x1, y1) || !INGRID(state, x2, y2)) return false;
/* We limit the maximum size of tiles to be ~2*sqrt(area); so,
* a 5x5 grid shouldn't have anything >10 tiles, a 20x20 grid
assert(nadd < MAX_TOADD);
sp = &SPACE(state, x, y);
assert(sp->type == s_tile);
- if (sp->flags & F_TILE_ASSOC) return 0;
+ if (sp->flags & F_TILE_ASSOC) return false;
toadd[nadd++] = sp;
}
}
dot->x, dot->y, dot->nassoc));
continue;
}
- if (dot_expand_or_move(state, dot, toadd, nadd)) return 1;
+ if (dot_expand_or_move(state, dot, toadd, nadd)) return true;
}
- return 0;
+ return false;
}
#ifdef STANDALONE_SOLVER
/* If we've got here we might want to put a dot down. Check
* if we can, and add one if so. */
- if (dot_is_possible(state, sp, 0)) {
+ if (dot_is_possible(state, sp, false)) {
add_dot(sp);
#ifdef STANDALONE_PICTURE_GENERATOR
if (picture) {
game_state *state = blank_game(params->w, params->h), *copy;
char *desc;
int *scratch, sz = state->sx*state->sy, i;
- int diff, ntries = 0, cc;
+ int diff, ntries = 0;
+ bool cc;
/* Random list of squares to try and process, one-by-one. */
scratch = snewn(sz, int);
for (i = 0; i < sz; i++) scratch[i] = i;
generate:
- clear_game(state, 1);
+ clear_game(state, true);
ntries++;
/* generate_pass(state, rs, scratch, 10, GP_DOTS); */
assert(cc);
copy = dup_game(state);
- clear_game(copy, 0);
+ clear_game(copy, false);
dbg_state(copy);
diff = solver_state(copy, params->diff);
free_game(copy);
for (i = 0; i < nposns; i++) {
int x, y, x0, y0, x1, y1, cx, cy, cn, cx0, cy0, cx1, cy1, tx, ty;
space *s0, *s1, *ts, *d0, *d1, *dn;
- int ok;
+ bool ok;
/* Coordinates of edge space */
x = posns[i] % state->sx;
}
copy = dup_game(state);
- clear_game(copy, 0);
+ clear_game(copy, false);
dbg_state(copy);
newdiff = solver_state(copy, params->diff);
free_game(copy);
return desc;
}
-static int dots_too_close(game_state *state)
+static bool dots_too_close(game_state *state)
{
/* Quick-and-dirty check, using half the solver:
* solver_obvious will only fail if the dots are
game_state *tmp = dup_game(state);
int ret = solver_obvious(tmp);
free_game(tmp);
- return (ret == -1) ? 1 : 0;
+ return ret == -1;
}
static game_state *load_game(const game_params *params, const char *desc,
*
*/
-/* Returns 1 if this tile is either already associated with this dot,
+/* Returns true if this tile is either already associated with this dot,
* or blank. */
-static int solver_expand_checkdot(space *tile, space *dot)
+static bool solver_expand_checkdot(space *tile, space *dot)
{
- if (!(tile->flags & F_TILE_ASSOC)) return 1;
- if (tile->dotx == dot->x && tile->doty == dot->y) return 1;
- return 0;
+ if (!(tile->flags & F_TILE_ASSOC)) return true;
+ if (tile->dotx == dot->x && tile->doty == dot->y) return true;
+ return false;
}
static void solver_expand_fromdot(game_state *state, space *dot, solver_ctx *sctx)
*/
for (i = 0; i < tosolve->sx*tosolve->sy; i++)
tosolve->grid[i].flags &= ~F_TILE_ASSOC;
- ret = diff_game(currstate, tosolve, 1);
+ ret = diff_game(currstate, tosolve, true);
free_game(tosolve);
return ret;
}
*/
struct game_ui {
- int dragging;
+ bool dragging;
int dx, dy; /* pixel coords of drag pos. */
int dotx, doty; /* grid coords of dot we're dragging from. */
int srcx, srcy; /* grid coords of drag start */
- int cur_x, cur_y, cur_visible;
+ int cur_x, cur_y;
+ bool cur_visible;
};
static game_ui *new_ui(const game_state *state)
game_ui *ui = snew(game_ui);
ui->dragging = false;
ui->cur_x = ui->cur_y = 1;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
return ui;
}
#define CURSOR_SIZE DOT_SIZE
struct game_drawstate {
- int started;
+ bool started;
int w, h;
int tilesize;
unsigned long *grid;
blitter *bl;
blitter *blmirror;
- int dragging, dragx, dragy;
+ bool dragging;
+ int dragx, dragy;
int *colour_scratch;
- int cx, cy, cur_visible;
+ int cx, cy;
+ bool cur_visible;
blitter *cur_bl;
};
char *ret;
game_state *tmp = dup_game(state);
solver_obvious(tmp);
- ret = diff_game(state, tmp, 0);
+ ret = diff_game(state, tmp, false);
free_game(tmp);
return ret;
}
if (button == LEFT_BUTTON) {
- ui->cur_visible = 0;
+ ui->cur_visible = false;
coord_round_to_edge(FROMCOORD((float)x), FROMCOORD((float)y),
&px, &py);
} else if (button == RIGHT_BUTTON) {
int px1, py1;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
px = (int)(2*FROMCOORD((float)x) + 0.5);
py = (int)(2*FROMCOORD((float)y) + 0.5);
else
return UI_UPDATE;
} else if (IS_CURSOR_MOVE(button)) {
- move_cursor(button, &ui->cur_x, &ui->cur_y, state->sx-1, state->sy-1, 0);
+ move_cursor(button, &ui->cur_x, &ui->cur_y, state->sx-1, state->sy-1, false);
if (ui->cur_x < 1) ui->cur_x = 1;
if (ui->cur_y < 1) ui->cur_y = 1;
- ui->cur_visible = 1;
+ ui->cur_visible = true;
if (ui->dragging) {
ui->dx = SCOORD(ui->cur_x);
ui->dy = SCOORD(ui->cur_y);
return UI_UPDATE;
} else if (IS_CURSOR_SELECT(button)) {
if (!ui->cur_visible) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
sp = &SPACE(state, ui->cur_x, ui->cur_y);
}
#endif
-static int check_complete(const game_state *state, int *dsf, int *colours)
+static bool check_complete(const game_state *state, int *dsf, int *colours)
{
int w = state->w, h = state->h;
- int x, y, i, ret;
+ int x, y, i;
+ bool ret;
- int free_dsf;
+ bool free_dsf;
struct sqdata {
int minx, miny, maxx, maxy;
int cx, cy;
- int valid, colour;
+ bool valid;
+ int colour;
} *sqdata;
if (!dsf) {
ret = true;
for (i = 0; i < w*h; i++) {
int ci = dsf_canonify(dsf, i);
- int thisok = sqdata[ci].valid;
+ bool thisok = sqdata[ci].valid;
if (colours)
colours[i] = thisok ? sqdata[ci].colour : 0;
ret = ret && thisok;
int x, y, ax, ay, n, dx, dy;
game_state *ret = dup_game(state);
space *sp, *dot;
- int currently_solving = false;
+ bool currently_solving = false;
debug(("%s\n", move));
#ifdef EDITOR
} else if (c == 'C') {
move++;
- clear_game(ret, 1);
+ clear_game(ret, true);
#endif
} else if (c == 'S') {
move++;
- ret->used_solve = 1;
+ ret->used_solve = true;
currently_solving = true;
} else
goto badmove;
goto badmove;
}
if (check_complete(ret, NULL, NULL))
- ret->completed = 1;
+ ret->completed = true;
return ret;
badmove:
struct game_drawstate *ds = snew(struct game_drawstate);
int i;
- ds->started = 0;
+ ds->started = false;
ds->w = state->w;
ds->h = state->h;
ds->cur_bl = NULL;
ds->cx = ds->cy = 0;
- ds->cur_visible = 0;
+ ds->cur_visible = false;
return ds;
}
float animtime, float flashtime)
{
int w = ds->w, h = ds->h;
- int x, y, flashing = false;
+ int x, y;
+ bool flashing = false;
int oppx, oppy;
if (flashtime > 0) {
sfree(temp);
}
-static int gen(game_params *p, random_state *rs, int debug)
+static int gen(game_params *p, random_state *rs, bool debug)
{
char *desc;
int diff;
printf("Generating a %dx%d %s puzzle.\n",
p->w, p->h, galaxies_diffnames[p->diff]);
- desc = new_game_desc(p, rs, NULL, 0);
+ desc = new_game_desc(p, rs, NULL, false);
state = new_game(NULL, p, desc);
dump_state(state);
int diff, n = 0, i, diffs[DIFF_MAX], ndots = 0, nspaces = 0;
#ifndef DEBUGGING
- solver_show_working = 0;
+ solver_show_working = false;
#endif
tt_start = tt_now = time(NULL);
for (i = 0; i < DIFF_MAX; i++) diffs[i] = 0;
printf("]\n");
while (1) {
- desc = new_game_desc(p, rs, NULL, 0);
+ desc = new_game_desc(p, rs, NULL, false);
st = new_game(NULL, p, desc);
diff = solver_state(st, p->diff);
nspaces += st->w*st->h;
char *id = NULL, *desc;
const char *err;
game_state *s;
- int diff, do_soak = 0, verbose = 0;
+ int diff;
+ bool do_soak = false, verbose = false;
random_state *rs;
time_t seed = time(NULL);
while (--argc > 0) {
char *p = *++argv;
if (!strcmp(p, "-v")) {
- verbose = 1;
+ verbose = true;
} else if (!strcmp(p, "--seed")) {
if (argc == 0) usage_exit("--seed needs an argument");
seed = (time_t)atoi(*++argv);
argc--;
} else if (!strcmp(p, "--soak")) {
- do_soak = 1;
+ do_soak = true;
} else if (*p == '-') {
usage_exit("unrecognised option");
} else {
p->w = random_upto(rs, 15) + 3;
p->h = random_upto(rs, 15) + 3;
p->diff = random_upto(rs, DIFF_UNREASONABLE);
- diff = gen(p, rs, 0);
+ diff = gen(p, rs, false);
}
return 0;
}
gen(p, rs, verbose);
} else {
#ifndef DEBUGGING
- solver_show_working = 1;
+ solver_show_working = true;
#endif
*desc++ = '\0';
decode_params(p, id);
*/
dots = snewn(g->num_dots, int);
for (i = 0; i < g->num_dots; i++) {
- dots[i] = true;
+ dots[i] = 1;
for (j = 0; j < g->num_dots; j++) {
if ((dotpairs[i*g->num_dots+j] >= 0) ^
(dotpairs[j*g->num_dots+i] >= 0))
- dots[i] = false; /* non-duplicated edge: coastal dot */
+ dots[i] = 0; /* non-duplicated edge: coastal dot */
}
}
dots[i] = 0;
for (i = 0; i < g->num_faces; i++) {
grid_face *f = g->faces + i;
- int keep = false;
+ bool keep = false;
for (k = 0; k < f->order; k++)
if (dsf_canonify(dsf, f->dots[k] - g->dots) == j)
keep = true;
if (keep) {
- faces[i] = true;
+ faces[i] = 1;
for (k = 0; k < f->order; k++)
- dots[f->dots[k]-g->dots] = true;
+ dots[f->dots[k]-g->dots] = 1;
}
}
/*
* Helper routines for grid_find_incentre.
*/
-static int solve_2x2_matrix(double mx[4], double vin[2], double vout[2])
+static bool solve_2x2_matrix(double mx[4], double vin[2], double vout[2])
{
double inv[4];
double det;
return true;
}
-static int solve_3x3_matrix(double mx[9], double vin[3], double vout[3])
+static bool solve_3x3_matrix(double mx[9], double vin[3], double vout[3])
{
double inv[9];
double det;
* _positive_ epsilon in both the x- and
* y-direction.)
*/
- int e, in = 0;
+ int e;
+ bool in = false;
for (e = 0; e < f->order; e++) {
int xs = f->edges[e]->dot1->x;
int xe = f->edges[e]->dot2->x;
denom = -denom;
}
if ((x - xs) * denom >= (y - ys) * num)
- in ^= 1;
+ in = !in;
}
}
#endif
int ncolours;
int bbox_l, bbox_r, bbox_u, bbox_d;
- int timer_active, timer_id;
+ bool timer_active;
+ int timer_id;
struct timeval last_time;
struct font *fonts;
int nfonts, fontsize;
config_item *cfg;
- int cfg_which, cfgret;
+ int cfg_which;
+ bool cfgret;
GtkWidget *cfgbox;
void *paste_data;
int paste_data_len;
char *filesel_name;
#endif
GSList *preset_radio;
- int preset_threaded;
+ bool preset_threaded;
GtkWidget *preset_custom;
GtkWidget *copy_menu_item;
#if !GTK_CHECK_VERSION(3,0,0)
- int drawing_area_shrink_pending;
- int menubar_is_local;
+ bool drawing_area_shrink_pending;
+ bool menubar_is_local;
#endif
#if GTK_CHECK_VERSION(3,0,0)
/*
* happen, the window's size_allocate handler does a fallback
* puzzle resize when it sees this flag still set to true.
*/
- int awaiting_resize_ack;
+ bool awaiting_resize_ack;
#endif
};
}
static void wipe_and_maybe_destroy_cairo(frontend *fe, cairo_t *cr,
- int destroy)
+ bool destroy)
{
cairo_set_source_rgb(cr, fe->colours[0], fe->colours[1], fe->colours[2]);
cairo_paint(cr);
#endif
}
-static int backing_store_ok(frontend *fe)
+static bool backing_store_ok(frontend *fe)
{
- return (!!fe->image);
+ return fe->image != NULL;
}
static void teardown_backing_store(frontend *fe)
gtk_main_quit();
}
-static int win_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
+static gint win_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
GObject *cancelbutton = G_OBJECT(data);
}
#if GTK_CHECK_VERSION(3,0,0)
-int message_box(GtkWidget *parent, const char *title, const char *msg,
- int centre, int type)
+bool message_box(GtkWidget *parent, const char *title, const char *msg,
+ bool centre, int type)
{
GtkWidget *window;
gint ret;
gtk_widget_destroy(GTK_WIDGET(data));
}
-int message_box(GtkWidget *parent, const char *title, const char *msg,
- int centre, int type)
+bool message_box(GtkWidget *parent, const char *title, const char *msg,
+ bool centre, int type)
{
GtkWidget *window, *hbox, *text, *button;
char *titles;
gtk_widget_destroy(fe->cfgbox);
}
-static int editbox_key(GtkWidget *widget, GdkEventKey *event, gpointer data)
+static gint editbox_key(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
/*
* GtkEntry has a nasty habit of eating the Return key, which
i->u.choices.selected = gtk_combo_box_get_active(combo);
}
-static int get_config(frontend *fe, int which)
+static bool get_config(frontend *fe, int which)
{
GtkWidget *w, *table, *cancel;
GtkBox *content_box, *button_box;
* Update the greying on the Copy menu option.
*/
if (fe->copy_menu_item) {
- int enabled = midend_can_format_as_text_now(fe->me);
+ bool enabled = midend_can_format_as_text_now(fe->me);
gtk_widget_set_sensitive(fe->copy_menu_item, enabled);
}
}
#if !GTK_CHECK_VERSION(3,0,0)
-static gboolean not_size_allocated_yet(GtkWidget *w)
+static bool not_size_allocated_yet(GtkWidget *w)
{
/*
* This function tests whether a widget has not yet taken up space
}
GdkAtom compound_text_atom, utf8_string_atom;
-int paste_initialised = false;
+bool paste_initialised = false;
static void set_selection(frontend *fe, GdkAtom selection)
{
#else
-static char *file_selector(frontend *fe, const char *title, int save)
+static char *file_selector(frontend *fe, const char *title, bool save)
{
char *filesel_name = NULL;
{
char *pname = argv[0];
char *error;
- int ngenerate = 0, print = false, px = 1, py = 1;
- int time_generation = false, test_solve = false, list_presets = false;
- int soln = false, colour = false;
+ int ngenerate = 0, px = 1, py = 1;
+ bool print = false;
+ bool time_generation = false, test_solve = false, list_presets = false;
+ bool soln = false, colour = false;
float scale = 1.0F;
float redo_proportion = 0.0F;
const char *savefile = NULL, *savesuffix = NULL;
char *arg = NULL;
int argtype = ARG_EITHER;
char *screenshot_file = NULL;
- int doing_opts = true;
+ bool doing_opts = true;
int ac = argc;
char **av = argv;
char errbuf[500];
struct game_params {
int ncolours, npegs, nguesses;
- int allow_blank, allow_multiple;
+ bool allow_blank, allow_multiple;
};
#define FEEDBACK_CORRECTPLACE 1
struct game_state {
game_params params;
pegrow *guesses; /* length params->nguesses */
- int *holds;
+ bool *holds;
pegrow solution;
int next_go; /* from 0 to nguesses-1;
if next_go == nguesses then they've lost. */
ret->npegs = 4;
ret->nguesses = 10;
- ret->allow_blank = 0;
- ret->allow_multiple = 1;
+ ret->allow_blank = false;
+ ret->allow_multiple = true;
return ret;
}
break;
case 'b':
- params->allow_blank = 1;
+ params->allow_blank = true;
break;
case 'B':
- params->allow_blank = 0;
+ params->allow_blank = false;
break;
case 'm':
- params->allow_multiple = 1;
+ params->allow_multiple = true;
break;
case 'M':
- params->allow_multiple = 0;
+ params->allow_multiple = false;
break;
default:
state->guesses = snewn(params->nguesses, pegrow);
for (i = 0; i < params->nguesses; i++)
state->guesses[i] = new_pegrow(params->npegs);
- state->holds = snewn(params->npegs, int);
+ state->holds = snewn(params->npegs, bool);
state->solution = new_pegrow(params->npegs);
bmp = hex2bin(desc, params->npegs);
state->solution->pegs[i] = (int)bmp[i];
sfree(bmp);
- memset(state->holds, 0, sizeof(int) * params->npegs);
+ memset(state->holds, 0, sizeof(bool) * params->npegs);
state->next_go = state->solved = 0;
return state;
ret->guesses = snewn(state->params.nguesses, pegrow);
for (i = 0; i < state->params.nguesses; i++)
ret->guesses[i] = dup_pegrow(state->guesses[i]);
- ret->holds = snewn(state->params.npegs, int);
- memcpy(ret->holds, state->holds, sizeof(int) * state->params.npegs);
+ ret->holds = snewn(state->params.npegs, bool);
+ memcpy(ret->holds, state->holds, sizeof(bool) * state->params.npegs);
ret->solution = dup_pegrow(state->solution);
return ret;
return NULL;
}
-static int is_markable(const game_params *params, pegrow pegs)
+static bool is_markable(const game_params *params, pegrow pegs)
{
- int i, nset = 0, nrequired, ret = 0;
+ int i, nset = 0, nrequired;
+ bool ret = false;
pegrow colcount = new_pegrow(params->ncolours);
nrequired = params->allow_blank ? 1 : params->npegs;
if (colcount->pegs[i] > 1) goto done;
}
}
- ret = 1;
+ ret = true;
done:
free_pegrow(colcount);
return ret;
struct game_ui {
game_params params;
pegrow curr_pegs; /* half-finished current move */
- int *holds;
+ bool *holds;
int colour_cur; /* position of up-down colour picker cursor */
int peg_cur; /* position of left-right peg picker cursor */
- int display_cur, markable;
+ bool display_cur, markable;
int drag_col, drag_x, drag_y; /* x and y are *center* of peg! */
int drag_opeg; /* peg index, if dragged from a peg (from current guess), otherwise -1 */
- int show_labels; /* label the colours with letters */
+ bool show_labels; /* label the colours with letters */
pegrow hint;
};
memset(ui, 0, sizeof(game_ui));
ui->params = state->params; /* structure copy */
ui->curr_pegs = new_pegrow(state->params.npegs);
- ui->holds = snewn(state->params.npegs, int);
- memset(ui->holds, 0, sizeof(int)*state->params.npegs);
+ ui->holds = snewn(state->params.npegs, bool);
+ memset(ui->holds, 0, sizeof(bool)*state->params.npegs);
ui->drag_opeg = -1;
return ui;
}
while (*p && isdigit((unsigned char)*p)) p++;
if (*p == '_') {
/* NB: old versions didn't store holds */
- ui->holds[i] = 1;
+ ui->holds[i] = true;
p++;
} else
- ui->holds[i] = 0;
+ ui->holds[i] = false;
if (*p == ',') p++;
}
ui->markable = is_markable(&ui->params, ui->curr_pegs);
* for undo. */
for (i = 0; i < newstate->solution->npegs; i++) {
if (newstate->solved)
- ui->holds[i] = 0;
+ ui->holds[i] = false;
else
ui->holds[i] = newstate->holds[i];
if (newstate->solved || (newstate->next_go == 0) || !ui->holds[i]) {
int guessx, guessy; /* origin of guesses */
int solnx, solny; /* origin of solution */
int hintw; /* no. of hint tiles we're wide per row */
- int w, h, started, solved;
+ int w, h;
+ bool started;
+ int solved;
int next_go;
ui->markable = true;
ui->peg_cur = state->params.npegs;
- ui->display_cur = 1;
+ ui->display_cur = true;
return;
increment_pegrow:
* should it ever happen, update the ui in some trivial way. This gives
* the user a sense of broken(ish)ness and futility. */
if (!ui->display_cur) {
- ui->display_cur = 1;
+ ui->display_cur = true;
} else if (state->params.npegs == 1) {
- ui->display_cur = 0;
+ ui->display_cur = false;
} else {
ui->peg_cur = (ui->peg_cur + 1) % state->params.npegs;
}
int over_guess = -1; /* zero-indexed */
int over_past_guess_y = -1; /* zero-indexed */
int over_past_guess_x = -1; /* zero-indexed */
- int over_hint = 0; /* zero or one */
+ bool over_hint = false;
char *ret = NULL;
int guess_ox = GUESS_X(from->next_go, 0);
over_guess = (x - guess_ox) / PEGOFF;
assert(over_guess >= 0 && over_guess < ds->solution->npegs);
} else {
- over_hint = 1;
+ over_hint = true;
}
} else if (x >= guess_ox && x < (guess_ox + GUESS_W) &&
y >= GUESS_OY && y < guess_oy) {
}
ui->drag_col = 0;
ui->drag_opeg = -1;
- ui->display_cur = 0;
+ ui->display_cur = false;
debug(("Stop dragging."));
ret = UI_UPDATE;
} else if (button == RIGHT_BUTTON) {
if (over_guess > -1) {
/* we use ths feedback in the game_ui to signify
* 'carry this peg to the next guess as well'. */
- ui->holds[over_guess] = 1 - ui->holds[over_guess];
+ ui->holds[over_guess] ^= 1;
ret = UI_UPDATE;
}
} else if (button == LEFT_RELEASE && over_hint && ui->markable) {
/* keyboard input */
if (button == CURSOR_UP || button == CURSOR_DOWN) {
- ui->display_cur = 1;
+ ui->display_cur = true;
if (button == CURSOR_DOWN && (ui->colour_cur+1) < from->params.ncolours)
ui->colour_cur++;
if (button == CURSOR_UP && ui->colour_cur > 0)
int maxcur = from->params.npegs;
if (ui->markable) maxcur++;
- ui->display_cur = 1;
+ ui->display_cur = true;
if (button == CURSOR_RIGHT && (ui->peg_cur+1) < maxcur)
ui->peg_cur++;
if (button == CURSOR_LEFT && ui->peg_cur > 0)
ui->peg_cur--;
ret = UI_UPDATE;
} else if (IS_CURSOR_SELECT(button)) {
- ui->display_cur = 1;
+ ui->display_cur = true;
if (ui->peg_cur == from->params.npegs) {
ret = encode_move(from, ui);
} else {
ret = UI_UPDATE;
}
} else if (button == 'D' || button == 'd' || button == '\b') {
- ui->display_cur = 1;
+ ui->display_cur = true;
set_peg(&from->params, ui, ui->peg_cur, 0);
ret = UI_UPDATE;
} else if (button == CURSOR_SELECT2) {
if (ui->peg_cur == from->params.npegs)
return NULL;
- ui->display_cur = 1;
- ui->holds[ui->peg_cur] = 1 - ui->holds[ui->peg_cur];
+ ui->display_cur = true;
+ ui->holds[ui->peg_cur] ^= 1;
ret = UI_UPDATE;
}
return ret;
ret->guesses[from->next_go]->pegs[i] = atoi(p);
while (*p && isdigit((unsigned char)*p)) p++;
if (*p == '_') {
- ret->holds[i] = 1;
+ ret->holds[i] = true;
p++;
} else
- ret->holds[i] = 0;
+ ret->holds[i] = false;
if (*p == ',') p++;
}
}
static void draw_peg(drawing *dr, game_drawstate *ds, int cx, int cy,
- int moving, int labelled, int col)
+ bool moving, bool labelled, int col)
{
/*
* Some platforms antialias circles, which means we shouldn't
}
static void guess_redraw(drawing *dr, game_drawstate *ds, int guess,
- pegrow src, int *holds, int cur_col, int force,
- int labelled)
+ pegrow src, bool *holds, int cur_col, bool force,
+ bool labelled)
{
pegrow dest;
int rowx, rowy, i, scol;
}
static void hint_redraw(drawing *dr, game_drawstate *ds, int guess,
- pegrow src, int force, int cursor, int markable)
+ pegrow src, bool force, bool cursor, bool markable)
{
pegrow dest = ds->guesses[guess];
int rowx, rowy, i, scol, col, hintlen;
- int need_redraw;
+ bool need_redraw;
int emptycol = (markable ? COL_FLASH : COL_EMPTY);
if (src) assert(src->npegs == dest->npegs);
int dir, const game_ui *ui,
float animtime, float flashtime)
{
- int i, new_move;
+ int i;
+ bool new_move;
new_move = (state->next_go != ds->next_go) || !ds->started;
for (i = state->params.nguesses - 1; i >= 0; i--) {
if (i < state->next_go || state->solved) {
/* this info is stored in the game_state already */
- guess_redraw(dr, ds, i, state->guesses[i], NULL, -1, 0,
+ guess_redraw(dr, ds, i, state->guesses[i], NULL, -1, false,
ui->show_labels);
hint_redraw(dr, ds, i, state->guesses[i],
- i == (state->next_go-1) ? 1 : 0, false, false);
+ i == (state->next_go-1), false, false);
} else if (i > state->next_go) {
/* we've not got here yet; it's blank. */
- guess_redraw(dr, ds, i, NULL, NULL, -1, 0, ui->show_labels);
- hint_redraw(dr, ds, i, NULL, 0, false, false);
+ guess_redraw(dr, ds, i, NULL, NULL, -1, false, ui->show_labels);
+ hint_redraw(dr, ds, i, NULL, false, false, false);
}
}
if (!state->solved) {
/* this is the one we're on; the (incomplete) guess is stored in
* the game_ui. */
guess_redraw(dr, ds, state->next_go, ui->curr_pegs,
- ui->holds, ui->display_cur ? ui->peg_cur : -1, 0,
+ ui->holds, ui->display_cur ? ui->peg_cur : -1, false,
ui->show_labels);
- hint_redraw(dr, ds, state->next_go, NULL, 1,
+ hint_redraw(dr, ds, state->next_go, NULL, true,
ui->display_cur && ui->peg_cur == state->params.npegs,
ui->markable);
}
}
ds->drag_col = ui->drag_col;
- ds->started = 1;
+ ds->started = true;
}
static float game_anim_length(const game_state *oldstate,
int gems;
char *grid;
int distance_moved;
- int dead;
- int cheated;
+ bool dead;
+ bool cheated;
int solnpos;
soln *soln;
};
*/
struct solver_scratch {
- unsigned char *reachable_from, *reachable_to;
+ bool *reachable_from, *reachable_to;
int *positions;
};
{
struct solver_scratch *sc = snew(struct solver_scratch);
- sc->reachable_from = snewn(w * h * DIRECTIONS, unsigned char);
- sc->reachable_to = snewn(w * h * DIRECTIONS, unsigned char);
+ sc->reachable_from = snewn(w * h * DIRECTIONS, bool);
+ sc->reachable_to = snewn(w * h * DIRECTIONS, bool);
sc->positions = snewn(w * h * DIRECTIONS, int);
return sc;
sfree(sc);
}
-static int can_go(int w, int h, char *grid,
- int x1, int y1, int dir1, int x2, int y2, int dir2)
+static bool can_go(int w, int h, char *grid,
+ int x1, int y1, int dir1, int x2, int y2, int dir2)
{
/*
* Returns true if we can transition directly from (x1,y1)
* flags set.
*/
- memset(sc->reachable_from, 0, wh * DIRECTIONS);
- memset(sc->reachable_to, 0, wh * DIRECTIONS);
+ memset(sc->reachable_from, 0, wh * DIRECTIONS * sizeof(bool));
+ memset(sc->reachable_to, 0, wh * DIRECTIONS * sizeof(bool));
/*
* Find the starting square.
assert(sy < h);
for (pass = 0; pass < 2; pass++) {
- unsigned char *reachable = (pass == 0 ? sc->reachable_from :
- sc->reachable_to);
+ bool *reachable = (pass == 0 ? sc->reachable_from : sc->reachable_to);
int sign = (pass == 0 ? +1 : -1);
int dir;
if (x2 >= 0 && x2 < w &&
y2 >= 0 && y2 < h &&
!reachable[i2]) {
- int ok;
+ bool ok;
#ifdef SOLVER_DIAGNOSTICS
printf(" trying point %d,%d,%d", x2, y2, d2);
#endif
float anim_length;
int flashtype;
int deaths;
- int just_made_move;
- int just_died;
+ bool just_made_move;
+ bool just_died;
};
static game_ui *new_ui(const game_state *state)
struct game_drawstate {
game_params p;
int tilesize;
- int started;
+ bool started;
unsigned short *grid;
blitter *player_background;
- int player_bg_saved, pbgx, pbgy;
+ bool player_bg_saved;
+ int pbgx, pbgy;
};
#define PREFERRED_TILESIZE 32
}
static void draw_player(drawing *dr, game_drawstate *ds, int x, int y,
- int dead, int hintdir)
+ bool dead, int hintdir)
{
if (dead) {
int coords[DIRECTIONS*4];
};
struct game_params {
- int w, diff, multiplication_only;
+ int w, diff;
+ bool multiplication_only;
};
struct clues {
struct clues *clues;
digit *grid;
int *pencil; /* bitmaps using bits 1<<1..1<<n */
- int completed, cheated;
+ bool completed, cheated;
};
static game_params *default_params(void)
* means 26, zb 27 etc).
*/
for (i = 0; i <= 2*w*(w-1); i++) {
- int x, y, p0, p1, edge;
+ int x, y, p0, p1;
+ bool edge;
if (i == 2*w*(w-1)) {
edge = true; /* terminating virtual edge */
dsf_init(dsf, a);
while (**p && (repn > 0 || **p != ',')) {
- int c, adv;
+ int c;
+ bool adv;
if (repn > 0) {
repn--;
for (i = 0; i < a; i++)
clues[i] = 0;
while (1) {
- int done_something = false;
+ bool done_something = false;
for (k = 0; k < 4; k++) {
long clue;
state->pencil[i] = 0;
}
- state->completed = state->cheated = false;
+ state->completed = false;
+ state->cheated = false;
return state;
}
struct game_ui {
/*
* These are the coordinates of the currently highlighted
- * square on the grid, if hshow = 1.
+ * square on the grid, if hshow is true.
*/
int hx, hy;
/*
* This indicates whether the current highlight is a
* pencil-mark one or a real one.
*/
- int hpencil;
+ bool hpencil;
/*
* This indicates whether or not we're showing the highlight
* (used to be hx = hy = -1); important so that when we're
* using the cursor keys it doesn't keep coming back at a
- * fixed position. When hshow = 1, pressing a valid number
- * or letter key or Space will enter that number or letter in the grid.
+ * fixed position. When true, pressing a valid number or letter
+ * key or Space will enter that number or letter in the grid.
*/
- int hshow;
+ bool hshow;
/*
* This indicates whether we're using the highlight as a cursor;
* it means that it doesn't vanish on a keypress, and that it is
* allowed on immutable squares.
*/
- int hcursor;
+ bool hcursor;
};
static game_ui *new_ui(const game_state *state)
game_ui *ui = snew(game_ui);
ui->hx = ui->hy = 0;
- ui->hpencil = ui->hshow = ui->hcursor = 0;
+ ui->hpencil = false;
+ ui->hshow = false;
+ ui->hcursor = false;
return ui;
}
*/
if (ui->hshow && ui->hpencil && !ui->hcursor &&
newstate->grid[ui->hy * w + ui->hx] != 0) {
- ui->hshow = 0;
+ ui->hshow = false;
}
}
struct game_drawstate {
int tilesize;
- int started;
+ bool started;
long *tiles;
long *errors;
char *minus_sign, *times_sign, *divide_sign;
};
-static int check_errors(const game_state *state, long *errors)
+static bool check_errors(const game_state *state, long *errors)
{
int w = state->par.w, a = w*w;
- int i, j, x, y, errs = false;
+ int i, j, x, y;
+ bool errs = false;
long *cluevals;
- int *full;
+ bool *full;
cluevals = snewn(a, long);
- full = snewn(a, int);
+ full = snewn(a, bool);
if (errors)
for (i = 0; i < a; i++) {
if (tx >= 0 && tx < w && ty >= 0 && ty < w) {
if (button == LEFT_BUTTON) {
if (tx == ui->hx && ty == ui->hy &&
- ui->hshow && ui->hpencil == 0) {
- ui->hshow = 0;
+ ui->hshow && !ui->hpencil) {
+ ui->hshow = false;
} else {
ui->hx = tx;
ui->hy = ty;
- ui->hshow = 1;
- ui->hpencil = 0;
+ ui->hshow = true;
+ ui->hpencil = false;
}
- ui->hcursor = 0;
+ ui->hcursor = false;
return UI_UPDATE;
}
if (button == RIGHT_BUTTON) {
if (state->grid[ty*w+tx] == 0) {
if (tx == ui->hx && ty == ui->hy &&
ui->hshow && ui->hpencil) {
- ui->hshow = 0;
+ ui->hshow = false;
} else {
- ui->hpencil = 1;
+ ui->hpencil = true;
ui->hx = tx;
ui->hy = ty;
- ui->hshow = 1;
+ ui->hshow = true;
}
} else {
- ui->hshow = 0;
+ ui->hshow = false;
}
- ui->hcursor = 0;
+ ui->hcursor = false;
return UI_UPDATE;
}
}
if (IS_CURSOR_MOVE(button)) {
- move_cursor(button, &ui->hx, &ui->hy, w, w, 0);
- ui->hshow = ui->hcursor = 1;
+ move_cursor(button, &ui->hx, &ui->hy, w, w, false);
+ ui->hshow = true;
+ ui->hcursor = true;
return UI_UPDATE;
}
if (ui->hshow &&
(button == CURSOR_SELECT)) {
- ui->hpencil = 1 - ui->hpencil;
- ui->hcursor = 1;
+ ui->hpencil ^= 1;
+ ui->hcursor = true;
return UI_UPDATE;
}
sprintf(buf, "%c%d,%d,%d",
(char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n);
- if (!ui->hcursor) ui->hshow = 0;
+ if (!ui->hcursor) ui->hshow = false;
return dupstr(buf);
}
}
static void draw_tile(drawing *dr, game_drawstate *ds, struct clues *clues,
- int x, int y, long tile, int only_one_op)
+ int x, int y, long tile, bool only_one_op)
{
int w = clues->w /* , a = w*w */;
int tx, ty, tw, th;
game_state *s;
char *id = NULL, *desc;
const char *err;
- int grade = false;
- int ret, diff, really_show_working = false;
+ bool grade = false;
+ int ret, diff;
+ bool really_show_working = false;
while (--argc > 0) {
char *p = *++argv;
* the puzzle internally before doing anything else.
*/
ret = -1; /* placate optimiser */
- solver_show_working = false;
+ solver_show_working = 0;
for (diff = 0; diff < DIFFCOUNT; diff++) {
memset(s->grid, 0, p->w * p->w);
ret = solver(p->w, s->clues->dsf, s->clues->clues,
else
printf("Difficulty rating: %s\n", keen_diffnames[ret]);
} else {
- solver_show_working = really_show_working;
+ solver_show_working = really_show_working ? 1 : 0;
memset(s->grid, 0, p->w * p->w);
ret = solver(p->w, s->clues->dsf, s->clues->clues,
s->grid, diff);
*/
int rows = 0;
for (i = 0; i < n; i++) {
- int ok = true;
+ bool ok = true;
for (j = 0; j < n; j++)
if (set[j] && grid[i*o+j]) {
ok = false;
}
if (rows >= n - count) {
- int progress = false;
+ bool progress = false;
/*
* We've got one! Now, for each row which _doesn't_
* positions in the cube to meddle with.
*/
for (i = 0; i < n; i++) {
- int ok = true;
+ bool ok = true;
for (j = 0; j < n; j++)
if (set[j] && grid[i*o+j]) {
ok = false;
solver->o = o;
solver->cube = snewn(o*o*o, unsigned char);
solver->grid = grid; /* write straight back to the input */
- memset(solver->cube, true, o*o*o);
+ memset(solver->cube, 1, o*o*o);
solver->row = snewn(o*o, unsigned char);
solver->col = snewn(o*o, unsigned char);
- memset(solver->row, false, o*o);
- memset(solver->col, false, o*o);
+ memset(solver->row, 0, o*o);
+ memset(solver->col, 0, o*o);
for (x = 0; x < o; x++)
for (y = 0; y < o; y++)
if (ret == 0 && i == diff_simple)
ret = latin_solver_diff_simple(solver);
if (ret == 0 && i == diff_set_0)
- ret = latin_solver_diff_set(solver, scratch, 0);
+ ret = latin_solver_diff_set(solver, scratch, false);
if (ret == 0 && i == diff_set_1)
- ret = latin_solver_diff_set(solver, scratch, 1);
+ ret = latin_solver_diff_set(solver, scratch, true);
if (ret == 0 && i == diff_forcing)
ret = latin_solver_forcing(solver, scratch);
of surrounding lights. For non-black squares,
the number of times it's lit. size h*w*/
unsigned int *flags; /* size h*w */
- int completed, used_solve;
+ bool completed, used_solve;
};
#define GRID(gs,grid,x,y) (gs->grid[(y)*((gs)->w) + (x)])
typedef struct {
int ox,oy;
int minx, maxx, miny, maxy;
- int include_origin;
+ bool include_origin;
} ll_data;
/* Macro that executes 'block' once per light in lld, including
memset(ret->lights, 0, ret->w * ret->h * sizeof(int));
ret->flags = snewn(ret->w * ret->h, unsigned int);
memset(ret->flags, 0, ret->w * ret->h * sizeof(unsigned int));
- ret->completed = ret->used_solve = 0;
+ ret->completed = false;
+ ret->used_solve = false;
return ret;
}
/* These are split up because occasionally functions are only
* interested in one particular aspect. */
-/* Returns non-zero if all grid spaces are lit. */
-static int grid_lit(game_state *state)
+/* Returns true if all grid spaces are lit. */
+static bool grid_lit(game_state *state)
{
int x, y;
for (y = 0; y < state->h; y++) {
if (GRID(state,flags,x,y) & F_BLACK) continue;
if (GRID(state,lights,x,y) == 0)
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
/* Returns non-zero if any lights are lit by other lights. */
-static int grid_overlap(game_state *state)
+static bool grid_overlap(game_state *state)
{
int x, y;
for (y = 0; y < state->h; y++) {
if (!(GRID(state, flags, x, y) & F_LIGHT)) continue;
if (GRID(state, lights, x, y) > 1)
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
-static int number_wrong(const game_state *state, int x, int y)
+static bool number_wrong(const game_state *state, int x, int y)
{
surrounds s;
int i, n, empty, lights = GRID(state, lights, x, y);
return (n > lights || (n + empty < lights));
}
-static int number_correct(game_state *state, int x, int y)
+static bool number_correct(game_state *state, int x, int y)
{
surrounds s;
int n = 0, i, lights = GRID(state, lights, x, y);
if (GRID(state,flags,s.points[i].x,s.points[i].y) & F_LIGHT)
n++;
}
- return (n == lights) ? 1 : 0;
+ return n == lights;
}
-/* Returns non-zero if any numbers add up incorrectly. */
-static int grid_addsup(game_state *state)
+/* Returns true if any numbers add up incorrectly. */
+static bool grid_addsup(game_state *state)
{
int x, y;
for (x = 0; x < state->w; x++) {
for (y = 0; y < state->h; y++) {
if (!(GRID(state, flags, x, y) & F_NUMBERED)) continue;
- if (!number_correct(state, x, y)) return 0;
+ if (!number_correct(state, x, y)) return false;
}
}
- return 1;
+ return true;
}
-static int grid_correct(game_state *state)
+static bool grid_correct(game_state *state)
{
if (grid_lit(state) &&
!grid_overlap(state) &&
- grid_addsup(state)) return 1;
- return 0;
+ grid_addsup(state)) return true;
+ return false;
}
/* --- Board initial setup (blacks, lights, numbers) --- */
-static void clean_board(game_state *state, int leave_blacks)
+static void clean_board(game_state *state, bool leave_blacks)
{
int x,y;
for (x = 0; x < state->w; x++) {
static void set_blacks(game_state *state, const game_params *params,
random_state *rs)
{
- int x, y, degree = 0, rotate = 0, nblack;
+ int x, y, degree = 0, nblack;
+ bool rotate = false;
int rh, rw, i;
int wodd = (state->w % 2) ? 1 : 0;
int hodd = (state->h % 2) ? 1 : 0;
int xs[4], ys[4];
switch (params->symm) {
- case SYMM_NONE: degree = 1; rotate = 0; break;
- case SYMM_ROT2: degree = 2; rotate = 1; break;
- case SYMM_REF2: degree = 2; rotate = 0; break;
- case SYMM_ROT4: degree = 4; rotate = 1; break;
- case SYMM_REF4: degree = 4; rotate = 0; break;
+ case SYMM_NONE: degree = 1; rotate = false; break;
+ case SYMM_ROT2: degree = 2; rotate = true; break;
+ case SYMM_REF2: degree = 2; rotate = false; break;
+ case SYMM_ROT4: degree = 4; rotate = true; break;
+ case SYMM_REF4: degree = 4; rotate = false; break;
default: assert(!"Unknown symmetry type");
}
if (params->symm == SYMM_ROT4 && (state->h != state->w))
}
/* clear, then randomise, required region. */
- clean_board(state, 0);
+ clean_board(state, false);
nblack = (rw * rh * params->blackpc) / 100;
for (i = 0; i < nblack; i++) {
do {
}
/* Fills in (does not allocate) a ll_data with all the tiles that would
- * be illuminated by a light at point (ox,oy). If origin=1 then the
+ * be illuminated by a light at point (ox,oy). If origin is true then the
* origin is included in this list. */
-static void list_lights(game_state *state, int ox, int oy, int origin,
+static void list_lights(game_state *state, int ox, int oy, bool origin,
ll_data *lld)
{
int x,y;
/* Makes sure a light is the given state, editing the lights table to suit the
* new state if necessary. */
-static void set_light(game_state *state, int ox, int oy, int on)
+static void set_light(game_state *state, int ox, int oy, bool on)
{
ll_data lld;
int diff = 0;
}
if (diff != 0) {
- list_lights(state,ox,oy,1,&lld);
+ list_lights(state,ox,oy,true,&lld);
FOREACHLIT(&lld, GRID(state,lights,lx,ly) += diff; );
}
}
{
ll_data lld;
- list_lights(state, x, y, 1, &lld);
+ list_lights(state, x, y, true, &lld);
FOREACHLIT(&lld, if (GRID(state,lights,lx,ly) == 1) { return 1; } );
return 0;
}
for (y = 0; y < state->h; y++) {
GRID(state, flags, x, y) &= ~F_MARK; /* we use this later. */
if (GRID(state, flags, x, y) & F_BLACK) continue;
- set_light(state, x, y, 1);
+ set_light(state, x, y, true);
}
}
x = numindices[i] % state->w;
if (!(GRID(state, flags, x, y) & F_LIGHT)) continue;
if (GRID(state, flags, x, y) & F_MARK) continue;
- list_lights(state, x, y, 0, &lld);
+ list_lights(state, x, y, false, &lld);
/* If we're not lighting any lights ourself, don't remove anything. */
n = 0;
FOREACHLIT(&lld, if (GRID(state,flags,lx,ly) & F_LIGHT) { n += check_dark(state,lx,ly); } );
if (n == 0) {
/* No, it wouldn't, so we can remove them all. */
- FOREACHLIT(&lld, set_light(state,lx,ly, 0); );
+ FOREACHLIT(&lld, set_light(state,lx,ly, false); );
GRID(state,flags,x,y) |= F_MARK;
}
*x = lx; *y = ly; (*n)++;
}
-static int try_solve_light(game_state *state, int ox, int oy,
- unsigned int flags, int lights)
+static bool try_solve_light(game_state *state, int ox, int oy,
+ unsigned int flags, int lights)
{
ll_data lld;
int sx = 0, sy = 0, n = 0;
- if (lights > 0) return 0;
- if (flags & F_BLACK) return 0;
+ if (lights > 0) return false;
+ if (flags & F_BLACK) return false;
/* We have an unlit square; count how many ways there are left to
* place a light that lights us (including this square); if only
* one, we must put a light there. Squares that could light us
* are, of course, the same as the squares we would light... */
- list_lights(state, ox, oy, 1, &lld);
+ list_lights(state, ox, oy, true, &lld);
FOREACHLIT(&lld, { tsl_callback(state, lx, ly, &sx, &sy, &n); });
if (n == 1) {
- set_light(state, sx, sy, 1);
+ set_light(state, sx, sy, true);
#ifdef SOLVER_DIAGNOSTICS
debug(("(%d,%d) can only be lit from (%d,%d); setting to LIGHT\n",
ox,oy,sx,sy));
if (verbose) debug_state(state);
#endif
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-static int could_place_light(unsigned int flags, int lights)
+static bool could_place_light(unsigned int flags, int lights)
{
- if (flags & (F_BLACK | F_IMPOSSIBLE)) return 0;
- return (lights > 0) ? 0 : 1;
+ if (flags & (F_BLACK | F_IMPOSSIBLE)) return false;
+ return !(lights > 0);
}
-static int could_place_light_xy(game_state *state, int x, int y)
+static bool could_place_light_xy(game_state *state, int x, int y)
{
int lights = GRID(state,lights,x,y);
unsigned int flags = GRID(state,flags,x,y);
- return (could_place_light(flags, lights)) ? 1 : 0;
+ return could_place_light(flags, lights);
}
/* For a given number square, determine whether we have enough info
* to unambiguously place its lights. */
-static int try_solve_number(game_state *state, int nx, int ny,
- unsigned int nflags, int nlights)
+static bool try_solve_number(game_state *state, int nx, int ny,
+ unsigned int nflags, int nlights)
{
surrounds s;
- int x, y, nl, ns, i, ret = 0, lights;
+ int x, y, nl, ns, i, lights;
+ bool ret = false;
unsigned int flags;
- if (!(nflags & F_NUMBERED)) return 0;
+ if (!(nflags & F_NUMBERED)) return false;
nl = nlights;
get_surrounds(state,nx,ny,&s);
ns = s.npoints;
s.points[i].f |= F_MARK;
}
}
- if (ns == 0) return 0; /* nowhere to put anything. */
+ if (ns == 0) return false; /* nowhere to put anything. */
if (nl == 0) {
/* we have placed all lights we need to around here; all remaining
* surrounds are therefore IMPOSSIBLE. */
for (i = 0; i < s.npoints; i++) {
if (!(s.points[i].f & F_MARK)) {
GRID(state,flags,s.points[i].x,s.points[i].y) |= F_IMPOSSIBLE;
- ret = 1;
+ ret = true;
}
}
#ifdef SOLVER_DIAGNOSTICS
GRID(state,flags,nx,ny) |= F_NUMBERUSED;
for (i = 0; i < s.npoints; i++) {
if (!(s.points[i].f & F_MARK)) {
- set_light(state, s.points[i].x,s.points[i].y, 1);
- ret = 1;
+ set_light(state, s.points[i].x,s.points[i].y, true);
+ ret = true;
}
}
#ifdef SOLVER_DIAGNOSTICS
static void trl_callback_discount(game_state *state, int dx, int dy,
struct setscratch *scratch, int n, void *ctx)
{
- int *didsth = (int *)ctx;
+ bool *didsth = (bool *)ctx;
int i;
if (GRID(state,flags,dx,dy) & F_IMPOSSIBLE) {
if (verbose) debug_state(state);
#endif
- *didsth = 1;
+ *didsth = true;
}
static void trl_callback_incn(game_state *state, int dx, int dy,
/* Find all squares that would rule out a light at (x,y) and call trl_cb
* with them: anything that would light (x,y)... */
- list_lights(state, x, y, 0, &lld);
+ list_lights(state, x, y, false, &lld);
FOREACHLIT(&lld, { if (could_place_light_xy(state, lx, ly)) { cb(state, lx, ly, scratch, n, ctx); } });
/* ... as well as any empty space (that isn't x,y) next to any clue square
}
#endif
-static int discount_set(game_state *state,
- struct setscratch *scratch, int n)
+static bool discount_set(game_state *state,
+ struct setscratch *scratch, int n)
{
- int i, besti, bestn, didsth = 0;
+ int i, besti, bestn;
+ bool didsth = false;
#ifdef SOLVER_DIAGNOSTICS
if (verbose > 1) debug_scratch("discount_set", scratch, n);
#endif
- if (n == 0) return 0;
+ if (n == 0) return false;
for (i = 0; i < n; i++) {
try_rule_out(state, scratch[i].x, scratch[i].y, scratch, n,
}
/* Construct a MAKESLIGHT set from an unlit square. */
-static int discount_unlit(game_state *state, int x, int y,
- struct setscratch *scratch)
+static bool discount_unlit(game_state *state, int x, int y,
+ struct setscratch *scratch)
{
ll_data lld;
- int n, didsth;
+ int n;
+ bool didsth;
#ifdef SOLVER_DIAGNOSTICS
if (verbose) debug(("Trying to discount for unlit square at (%d,%d).\n", x, y));
discount_clear(state, scratch, &n);
- list_lights(state, x, y, 1, &lld);
+ list_lights(state, x, y, true, &lld);
FOREACHLIT(&lld, { unlit_cb(state, lx, ly, scratch, &n); });
didsth = discount_set(state, scratch, n);
#ifdef SOLVER_DIAGNOSTICS
* subset of size N-M+1 of those N spaces forms such a set.
*/
-static int discount_clue(game_state *state, int x, int y,
+static bool discount_clue(game_state *state, int x, int y,
struct setscratch *scratch)
{
- int slen, m = GRID(state, lights, x, y), n, i, didsth = 0, lights;
+ int slen, m = GRID(state, lights, x, y), n, i, lights;
+ bool didsth = false;
unsigned int flags;
surrounds s, sempty;
combi_ctx *combi;
- if (m == 0) return 0;
+ if (m == 0) return false;
#ifdef SOLVER_DIAGNOSTICS
if (verbose) debug(("Trying to discount for sets at clue (%d,%d).\n", x, y));
}
}
n = sempty.npoints; /* sempty is now a surrounds of only blank squares. */
- if (n == 0) return 0; /* clue is full already. */
+ if (n == 0) return false; /* clue is full already. */
- if (m < 0 || m > n) return 0; /* become impossible. */
+ if (m < 0 || m > n) return false; /* become impossible. */
combi = new_combi(n - m + 1, n);
while (next_combi(combi)) {
scratch[slen].y = sempty.points[combi->a[i]].y;
slen++;
}
- if (discount_set(state, scratch, slen)) didsth = 1;
+ if (discount_set(state, scratch, slen)) didsth = true;
}
free_combi(combi);
#ifdef SOLVER_DIAGNOSTICS
int *maxdepth)
{
unsigned int flags;
- int x, y, didstuff, ncanplace, lights;
+ int x, y, ncanplace, lights;
+ bool didstuff;
int bestx, besty, n, bestn, copy_soluble, self_soluble, ret, maxrecurse = 0;
game_state *scopy;
ll_data lld;
if (grid_correct(state)) { ret = 1; goto done; }
ncanplace = 0;
- didstuff = 0;
+ didstuff = false;
/* These 2 loops, and the functions they call, are the critical loops
* for timing; any optimisations should look here first. */
for (x = 0; x < state->w; x++) {
lights = GRID(state,lights,x,y);
ncanplace += could_place_light(flags, lights);
- if (try_solve_light(state, x, y, flags, lights)) didstuff = 1;
- if (try_solve_number(state, x, y, flags, lights)) didstuff = 1;
+ if (try_solve_light(state, x, y, flags, lights))
+ didstuff = true;
+ if (try_solve_number(state, x, y, flags, lights))
+ didstuff = true;
}
}
if (didstuff) continue;
if (!(flags & F_BLACK) && lights == 0) {
if (discount_unlit(state, x, y, sscratch)) {
- didstuff = 1;
+ didstuff = true;
goto reduction_success;
}
} else if (flags & F_NUMBERED) {
if (discount_clue(state, x, y, sscratch)) {
- didstuff = 1;
+ didstuff = true;
goto reduction_success;
}
}
if (!could_place_light(flags, lights)) continue;
n = 0;
- list_lights(state, x, y, 1, &lld);
+ list_lights(state, x, y, true, &lld);
FOREACHLIT(&lld, { if (GRID(state,lights,lx,ly) == 0) n++; });
if (n > bestn) {
bestn = n; bestx = x; besty = y;
#ifdef SOLVER_DIAGNOSTICS
debug(("Recursing #2: trying (%d,%d) as LIGHT\n", bestx, besty));
#endif
- set_light(scopy, bestx, besty, 1);
+ set_light(scopy, bestx, besty, true);
copy_soluble = solve_sub(scopy, solve_flags, depth+1, maxdepth);
/* If we wanted a unique solution but we hit our recursion limit
for (x = 0; x < state->w; x++) {
for (y = 0; y < state->h; y++) {
if (GRID(state,flags,x,y) & F_LIGHT)
- set_light(state,x,y,0);
+ set_light(state,x,y,false);
GRID(state,flags,x,y) &= ~F_IMPOSSIBLE;
GRID(state,flags,x,y) &= ~F_NUMBERUSED;
}
}
}
-static int puzzle_is_good(game_state *state, int difficulty)
+static bool puzzle_is_good(game_state *state, int difficulty)
{
int nsol, mdepth = 0;
unsigned int sflags = flags_from_difficulty(difficulty);
/* if we wanted an easy puzzle, make sure we didn't need recursion. */
if (!(sflags & F_SOLVE_ALLOWRECURSE) && mdepth > 0) {
debug(("Ignoring recursive puzzle.\n"));
- return 0;
+ return false;
}
debug(("%d solutions found.\n", nsol));
- if (nsol <= 0) return 0;
- if (nsol > 1) return 0;
- return 1;
+ if (nsol <= 0) return false;
+ if (nsol > 1) return false;
+ return true;
}
/* --- New game creation and user input code. --- */
}
struct game_ui {
- int cur_x, cur_y, cur_visible;
+ int cur_x, cur_y;
+ bool cur_visible;
};
static game_ui *new_ui(const game_state *state)
{
game_ui *ui = snew(game_ui);
- ui->cur_x = ui->cur_y = ui->cur_visible = 0;
+ ui->cur_x = ui->cur_y = 0;
+ ui->cur_visible = false;
return ui;
}
const game_state *newstate)
{
if (newstate->completed)
- ui->cur_visible = 0;
+ ui->cur_visible = false;
}
#define DF_BLACK 1 /* black square */
int tilesize, crad;
int w, h;
unsigned int *flags; /* width * height */
- int started;
+ bool started;
};
if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
if (ui->cur_visible)
nullret = empty;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
cx = FROMCOORD(x);
cy = FROMCOORD(y);
action = (button == LEFT_BUTTON) ? FLIP_LIGHT : FLIP_IMPOSSIBLE;
action = (button == 'i' || button == 'I' || button == CURSOR_SELECT2) ?
FLIP_IMPOSSIBLE : FLIP_LIGHT;
}
- ui->cur_visible = 1;
+ ui->cur_visible = true;
} else if (IS_CURSOR_MOVE(button)) {
- move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, 0);
- ui->cur_visible = 1;
+ move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, false);
+ ui->cur_visible = true;
nullret = empty;
} else
return NULL;
/* LIGHT and IMPOSSIBLE are mutually exclusive. */
if (c == 'L') {
GRID(ret, flags, x, y) &= ~F_IMPOSSIBLE;
- set_light(ret, x, y, (flags & F_LIGHT) ? 0 : 1);
+ set_light(ret, x, y, !(flags & F_LIGHT));
} else {
- set_light(ret, x, y, 0);
+ set_light(ret, x, y, false);
GRID(ret, flags, x, y) ^= F_IMPOSSIBLE;
}
move += n;
move++;
else if (*move) goto badmove;
}
- if (grid_correct(ret)) ret->completed = 1;
+ if (grid_correct(ret)) ret->completed = true;
return ret;
badmove:
for (i = 0; i < ds->w*ds->h; i++)
ds->flags[i] = -1;
- ds->started = 0;
+ ds->started = false;
return ds;
}
#define HINT_NUMBERS
static unsigned int tile_flags(game_drawstate *ds, const game_state *state,
- const game_ui *ui, int x, int y, int flashing)
+ const game_ui *ui, int x, int y, bool flashing)
{
unsigned int flags = GRID(state, flags, x, y);
int lights = GRID(state, lights, x, y);
int dir, const game_ui *ui,
float animtime, float flashtime)
{
- int flashing = false;
+ bool flashing = false;
int x,y;
if (flashtime) flashing = (int)(flashtime * 3 / FLASH_TIME) != 1;
draw_update(dr, 0, 0,
TILE_SIZE * ds->w + 2 * BORDER,
TILE_SIZE * ds->h + 2 * BORDER);
- ds->started = 1;
+ ds->started = true;
}
for (x = 0; x < ds->w; x++) {
/* 'board' is an array of enum face_colour, indicating which faces are
* currently black/white/grey. 'colour' is FACE_WHITE or FACE_BLACK.
* Returns whether it's legal to colour the given face with this colour. */
-static int can_colour_face(grid *g, char* board, int face_index,
- enum face_colour colour)
+static bool can_colour_face(grid *g, char* board, int face_index,
+ enum face_colour colour)
{
int i, j;
grid_face *test_face = g->faces + face_index;
grid_face *starting_face, *current_face;
grid_dot *starting_dot;
int transitions;
- int current_state, s; /* booleans: equal or not-equal to 'colour' */
- int found_same_coloured_neighbour = false;
+ bool current_state, s; /* equal or not-equal to 'colour' */
+ bool found_same_coloured_neighbour = false;
assert(board[face_index] != colour);
/* Can only consider a face for colouring if it's adjacent to a face
tree234 *lightable_faces_sorted;
tree234 *darkable_faces_sorted;
int *face_list;
- int do_random_pass;
+ bool do_random_pass;
/* Make a board */
memset(board, FACE_GREY, num_faces);
while (true) {
/* Remember whether a flip occurred during this pass */
- int flipped = false;
+ bool flipped = false;
for (i = 0; i < num_faces; ++i) {
int j = face_list[i];
* YES, NO or UNKNOWN */
char *lines;
- unsigned char *line_errors;
- int exactly_one_loop;
+ bool *line_errors;
+ bool exactly_one_loop;
- int solved;
- int cheated;
+ bool solved;
+ bool cheated;
/* Used in game_text_format(), so that it knows what type of
* grid it's trying to render as ASCII text. */
char *dot_no_count;
char *face_yes_count;
char *face_no_count;
- char *dot_solved, *face_solved;
+ bool *dot_solved, *face_solved;
int *dotdsf;
/* Information for Normal level deductions:
struct game_drawstate {
- int started;
+ bool started;
int tilesize;
- int flashing;
+ bool flashing;
int *textx, *texty;
char *lines;
- char *clue_error;
- char *clue_satisfied;
+ bool *clue_error;
+ bool *clue_satisfied;
};
static const char *validate_desc(const game_params *params, const char *desc);
ret->lines = snewn(state->game_grid->num_edges, char);
memcpy(ret->lines, state->lines, state->game_grid->num_edges);
- ret->line_errors = snewn(state->game_grid->num_edges, unsigned char);
- memcpy(ret->line_errors, state->line_errors, state->game_grid->num_edges);
+ ret->line_errors = snewn(state->game_grid->num_edges, bool);
+ memcpy(ret->line_errors, state->line_errors,
+ state->game_grid->num_edges * sizeof(bool));
ret->exactly_one_loop = state->exactly_one_loop;
ret->grid_type = state->grid_type;
ret->looplen[i] = 1;
}
- ret->dot_solved = snewn(num_dots, char);
- ret->face_solved = snewn(num_faces, char);
- memset(ret->dot_solved, false, num_dots);
- memset(ret->face_solved, false, num_faces);
+ ret->dot_solved = snewn(num_dots, bool);
+ ret->face_solved = snewn(num_faces, bool);
+ memset(ret->dot_solved, 0, num_dots * sizeof(bool));
+ memset(ret->face_solved, 0, num_faces * sizeof(bool));
ret->dot_yes_count = snewn(num_dots, char);
memset(ret->dot_yes_count, 0, num_dots);
memcpy(ret->looplen, sstate->looplen,
num_dots * sizeof(int));
- ret->dot_solved = snewn(num_dots, char);
- ret->face_solved = snewn(num_faces, char);
- memcpy(ret->dot_solved, sstate->dot_solved, num_dots);
- memcpy(ret->face_solved, sstate->face_solved, num_faces);
+ ret->dot_solved = snewn(num_dots, bool);
+ ret->face_solved = snewn(num_faces, bool);
+ memcpy(ret->dot_solved, sstate->dot_solved, num_dots * sizeof(bool));
+ memcpy(ret->face_solved, sstate->face_solved, num_faces * sizeof(bool));
ret->dot_yes_count = snewn(num_dots, char);
memcpy(ret->dot_yes_count, sstate->dot_yes_count, num_dots);
int i;
ds->tilesize = 0;
- ds->started = 0;
+ ds->started = false;
ds->lines = snewn(num_edges, char);
- ds->clue_error = snewn(num_faces, char);
- ds->clue_satisfied = snewn(num_faces, char);
+ ds->clue_error = snewn(num_faces, bool);
+ ds->clue_satisfied = snewn(num_faces, bool);
ds->textx = snewn(num_faces, int);
ds->texty = snewn(num_faces, int);
- ds->flashing = 0;
+ ds->flashing = false;
memset(ds->lines, LINE_UNKNOWN, num_edges);
- memset(ds->clue_error, 0, num_faces);
- memset(ds->clue_satisfied, 0, num_faces);
+ memset(ds->clue_error, 0, num_faces * sizeof(bool));
+ memset(ds->clue_satisfied, 0, num_faces * sizeof(bool));
for (i = 0; i < num_faces; i++)
ds->textx[i] = ds->texty[i] = -1;
/* Sets the line (with index i) to the new state 'line_new', and updates
* the cached counts of any affected faces and dots.
* Returns true if this actually changed the line's state. */
-static int solver_set_line(solver_state *sstate, int i,
- enum line_state line_new
+static bool solver_set_line(solver_state *sstate, int i,
+ enum line_state line_new
#ifdef SHOW_WORKING
- , const char *reason
+ , const char *reason
#endif
- )
+ )
{
game_state *state = sstate->state;
grid *g;
* Returns true if the dots were already linked, ie if they are part of a
* closed loop, and false otherwise.
*/
-static int merge_dots(solver_state *sstate, int edge_index)
+static bool merge_dots(solver_state *sstate, int edge_index)
{
int i, j, len;
grid *g = sstate->state->game_grid;
/* Merge two lines because the solver has deduced that they must be either
* identical or opposite. Returns true if this is new information, otherwise
* false. */
-static int merge_lines(solver_state *sstate, int i, int j, bool inverse
+static bool merge_lines(solver_state *sstate, int i, int j, bool inverse
#ifdef SHOW_WORKING
- , const char *reason
+ , const char *reason
#endif
- )
+ )
{
bool inv_tmp;
/* Set all lines bordering a dot of type old_type to type new_type
* Return value tells caller whether this function actually did anything */
-static int dot_setall(solver_state *sstate, int dot,
- char old_type, char new_type)
+static bool dot_setall(solver_state *sstate, int dot,
+ char old_type, char new_type)
{
- int retval = false, r;
+ bool retval = false, r;
game_state *state = sstate->state;
grid *g;
grid_dot *d;
int line_index = d->edges[i] - g->edges;
if (state->lines[line_index] == old_type) {
r = solver_set_line(sstate, line_index, new_type);
- assert(r == true);
+ assert(r);
retval = true;
}
}
}
/* Set all lines bordering a face of type old_type to type new_type */
-static int face_setall(solver_state *sstate, int face,
- char old_type, char new_type)
+static bool face_setall(solver_state *sstate, int face,
+ char old_type, char new_type)
{
- int retval = false, r;
+ bool retval = false, r;
game_state *state = sstate->state;
grid *g;
grid_face *f;
int line_index = f->edges[i] - g->edges;
if (state->lines[line_index] == old_type) {
r = solver_set_line(sstate, line_index, new_type);
- assert(r == true);
+ assert(r);
retval = true;
}
}
}
-static int game_has_unique_soln(const game_state *state, int diff)
+static bool game_has_unique_soln(const game_state *state, int diff)
{
- int ret;
+ bool ret;
solver_state *sstate_new;
solver_state *sstate = new_solver_state((game_state *)state, diff);
state->clues = snewn(g->num_faces, signed char);
state->lines = snewn(g->num_edges, char);
- state->line_errors = snewn(g->num_edges, unsigned char);
+ state->line_errors = snewn(g->num_edges, bool);
state->exactly_one_loop = false;
state->grid_type = params->type;
newboard_please:
memset(state->lines, LINE_UNKNOWN, g->num_edges);
- memset(state->line_errors, 0, g->num_edges);
+ memset(state->line_errors, 0, g->num_edges * sizeof(bool));
- state->solved = state->cheated = false;
+ state->solved = false;
+ state->cheated = false;
/* Get a new random solvable board with all its clues filled in. Yes, this
* can loop for ever if the params are suitably unfavourable, but
state->clues = snewn(num_faces, signed char);
state->lines = snewn(num_edges, char);
- state->line_errors = snewn(num_edges, unsigned char);
+ state->line_errors = snewn(num_edges, bool);
state->exactly_one_loop = false;
state->solved = state->cheated = false;
}
memset(state->lines, LINE_UNKNOWN, num_edges);
- memset(state->line_errors, 0, num_edges);
+ memset(state->line_errors, 0, num_edges * sizeof(bool));
return state;
}
/* Calculates the line_errors data, and checks if the current state is a
* solution */
-static int check_completion(game_state *state)
+static bool check_completion(game_state *state)
{
grid *g = state->game_grid;
- int i, ret;
+ int i;
+ bool ret;
int *dsf, *component_state;
int nsilly, nloop, npath, largest_comp, largest_size, total_pathsize;
enum { COMP_NONE, COMP_LOOP, COMP_PATH, COMP_SILLY, COMP_EMPTY };
- memset(state->line_errors, 0, g->num_edges);
+ memset(state->line_errors, 0, g->num_edges * sizeof(bool));
/*
* Find loops in the grid, and determine whether the puzzle is
#endif
return ret;
}
-static int is_atleastone(const char *dline_array, int index)
+static bool is_atleastone(const char *dline_array, int index)
{
return BIT_SET(dline_array[index], 0);
}
-static int set_atleastone(char *dline_array, int index)
+static bool set_atleastone(char *dline_array, int index)
{
return SET_BIT(dline_array[index], 0);
}
-static int is_atmostone(const char *dline_array, int index)
+static bool is_atmostone(const char *dline_array, int index)
{
return BIT_SET(dline_array[index], 1);
}
-static int set_atmostone(char *dline_array, int index)
+static bool set_atmostone(char *dline_array, int index)
{
return SET_BIT(dline_array[index], 1);
}
* will find the opposite UNKNOWNS (if they are adjacent to one another)
* and set their corresponding dline to atleastone. (Setting atmostone
* already happens in earlier dline deductions) */
-static int dline_set_opp_atleastone(solver_state *sstate,
- grid_dot *d, int edge)
+static bool dline_set_opp_atleastone(solver_state *sstate,
+ grid_dot *d, int edge)
{
game_state *state = sstate->state;
grid *g = state->game_grid;
/* Set pairs of lines around this face which are known to be identical, to
* the given line_state */
-static int face_setall_identical(solver_state *sstate, int face_index,
- enum line_state line_new)
+static bool face_setall_identical(solver_state *sstate, int face_index,
+ enum line_state line_new)
{
/* can[dir] contains the canonical line associated with the line in
* direction dir from the square in question. Similarly inv[dir] is
* whether or not the line in question is inverse to its canonical
* element. */
- int retval = false;
+ bool retval = false;
game_state *state = sstate->state;
grid *g = state->game_grid;
grid_face *f = g->faces + face_index;
for (j = 0; j < f->order; j++) {
e = f->edges[j] - g->edges;
if (state->lines[e] == LINE_UNKNOWN && e != e1 && e != e2) {
- int r = solver_set_line(sstate, e, LINE_YES);
+ bool r = solver_set_line(sstate, e, LINE_YES);
assert(r);
diff = min(diff, DIFF_EASY);
}
/* Infer linedsf from dline flags */
if (is_atmostone(dlines, dline_index)
&& is_atleastone(dlines, dline_index)) {
- if (merge_lines(sstate, line1_index, line2_index, 1))
+ if (merge_lines(sstate, line1_index, line2_index, true))
diff = min(diff, DIFF_HARD);
}
}
game_state *state = sstate->state;
grid *g = state->game_grid;
int shortest_chainlen = g->num_dots;
- int loop_found = false;
+ bool loop_found = false;
int dots_connected;
- int progress = false;
+ bool progress = false;
int i;
/*
* make.
*/
progress = solver_set_line(sstate, i, val);
- assert(progress == true);
+ assert(progress);
if (val == LINE_YES) {
sstate->solver_status = SOLVER_AMBIGUOUS;
goto finished_loop_deductionsing;
draw_circle(dr, x, y, 2, COL_FOREGROUND, COL_FOREGROUND);
}
-static int boxes_intersect(int x0, int y0, int w0, int h0,
- int x1, int y1, int w1, int h1)
+static bool boxes_intersect(int x0, int y0, int w0, int h0,
+ int x1, int y1, int w1, int h1)
{
/*
* Two intervals intersect iff neither is wholly on one side of
grid *g = state->game_grid;
int border = BORDER(ds->tilesize);
int i;
- int flash_changed;
- int redraw_everything = false;
+ bool flash_changed;
+ bool redraw_everything = false;
int edges[REDRAW_OBJECTS_LIMIT], nedges = 0;
int faces[REDRAW_OBJECTS_LIMIT], nfaces = 0;
grid_face *f = g->faces + i;
int sides = f->order;
int yes_order, no_order;
- int clue_mistake;
- int clue_satisfied;
+ bool clue_mistake;
+ bool clue_satisfied;
int n = state->clues[i];
if (n < 0)
continue;
game_state *s;
char *id = NULL, *desc;
const char *err;
- int grade = false;
+ bool grade = false;
int ret, diff;
#if 0 /* verbose solver not supported here (yet) */
- int really_verbose = false;
+ bool really_verbose = false;
#endif
while (--argc > 0) {
#include "puzzles.h"
#ifdef STANDALONE_SOLVER
-int verbose = 0;
+bool verbose = 0;
#endif
enum {
/* Game parameter functions. */
struct game_params {
- int w, h, diff, stripclues;
+ int w, h, diff;
+ bool stripclues;
};
#define DEFAULT_PRESET 2
if (*string) string++;
}
- ret->stripclues = 0;
+ ret->stripclues = false;
if (*string == 'S') {
string++;
- ret->stripclues = 1;
+ ret->stripclues = true;
}
}
int w, h, wh;
int *grid; /* size w*h, for cell state (pos/neg) */
unsigned int *flags; /* size w*h */
- int solved, completed, numbered;
- unsigned char *counts_done;
+ bool solved, completed, numbered;
+ bool *counts_done;
struct game_common *common; /* domino layout never changes. */
};
{
int i;
- ret->solved = ret->completed = ret->numbered = 0;
+ ret->solved = false;
+ ret->completed = false;
+ ret->numbered = false;
memset(ret->common->rowcount, 0, ret->h*3*sizeof(int));
memset(ret->common->colcount, 0, ret->w*3*sizeof(int));
- memset(ret->counts_done, 0, (ret->h + ret->w) * 2 * sizeof(unsigned char));
+ memset(ret->counts_done, 0, (ret->h + ret->w) * 2 * sizeof(bool));
for (i = 0; i < ret->wh; i++) {
ret->grid[i] = EMPTY;
ret->grid = snewn(ret->wh, int);
ret->flags = snewn(ret->wh, unsigned int);
- ret->counts_done = snewn((ret->h + ret->w) * 2, unsigned char);
+ ret->counts_done = snewn((ret->h + ret->w) * 2, bool);
ret->common = snew(struct game_common);
ret->common->refcount = 1;
dest->grid = snewn(dest->wh, int);
memcpy(dest->grid, src->grid, dest->wh*sizeof(int));
- dest->counts_done = snewn((dest->h + dest->w) * 2, unsigned char);
+ dest->counts_done = snewn((dest->h + dest->w) * 2, bool);
memcpy(dest->counts_done, src->counts_done,
- (dest->h + dest->w) * 2 * sizeof(unsigned char));
+ (dest->h + dest->w) * 2 * sizeof(bool));
dest->flags = snewn(dest->wh, unsigned int);
memcpy(dest->flags, src->flags, dest->wh*sizeof(unsigned int));
}
}
/* Success. */
- state->numbered = 1;
+ state->numbered = true;
goto done;
badchar:
}
static void check_rowcol(game_state *state, int num, int roworcol, int which,
- int *wrong, int *incomplete)
+ bool *wrong, bool *incomplete)
{
int count, target = mkrowcol(state, num, roworcol).targets[which];
if (target == -1) return; /* no number to check against. */
count = count_rowcol(state, num, roworcol, which);
- if (count < target) *incomplete = 1;
- if (count > target) *wrong = 1;
+ if (count < target) *incomplete = true;
+ if (count > target) *wrong = true;
}
static int check_completion(game_state *state)
{
int i, j, x, y, idx, w = state->w, h = state->h;
- int which = POSITIVE, wrong = 0, incomplete = 0;
+ int which = POSITIVE;
+ bool wrong = false, incomplete = false;
/* Check row and column counts for magnets. */
for (which = POSITIVE, j = 0; j < 2; which = OPPOSITE(which), j++) {
continue; /* no domino here */
if (!(state->flags[idx] & GS_SET))
- incomplete = 1;
+ incomplete = true;
which = state->grid[idx];
if (which != NEUTRAL) {
#define CHECK(xx,yy) do { \
if (INGRID(state,xx,yy) && \
(state->grid[(yy)*w+(xx)] == which)) { \
- wrong = 1; \
+ wrong = true; \
state->flags[(yy)*w+(xx)] |= GS_ERROR; \
state->flags[y*w+x] |= GS_ERROR; \
} \
static int solve_advancedfull(game_state *state, rowcol rc, int *counts)
{
- int i, j, nfound = 0, clearpos = 0, clearneg = 0, ret = 0;
+ int i, j, nfound = 0, ret = 0;
+ bool clearpos = false, clearneg = false;
/* For this row/col, look for a domino entirely within the row where
* both ends can only be + or - (but isn't held).
if (rc.targets[POSITIVE] >= 0 && counts[POSITIVE] == rc.targets[POSITIVE]) {
debug(("%s %d has now filled POSITIVE:", rc.name, rc.num));
- clearpos = 1;
+ clearpos = true;
}
if (rc.targets[NEGATIVE] >= 0 && counts[NEGATIVE] == rc.targets[NEGATIVE]) {
debug(("%s %d has now filled NEGATIVE:", rc.name, rc.num));
- clearneg = 1;
+ clearneg = true;
}
if (!clearpos && !clearneg) return 0;
static int solve_oddlength(game_state *state, rowcol rc, int *counts)
{
int i, j, ret = 0, extra, tpos, tneg;
- int start = -1, length = 0, inempty = 0, startodd = -1;
+ int start = -1, length = 0, startodd = -1;
+ bool inempty = false;
/* need zero neutral cells still to find... */
if (rc.targets[NEUTRAL] != counts[NEUTRAL])
if (startodd != -1) goto twoodd;
startodd = start;
}
- inempty = 0;
+ inempty = false;
}
} else {
if (inempty)
else {
start = i;
length = 1;
- inempty = 1;
+ inempty = true;
}
}
}
* or to the #remaining negative, no empty cells can be neutral. */
static int solve_countdominoes_neutral(game_state *state, rowcol rc, int *counts)
{
- int i, j, ndom = 0, nonn = 0, ret = 0;
+ int i, j, ndom = 0, ret = 0;
+ bool nonn = false;
if ((rc.targets[POSITIVE] == -1) && (rc.targets[NEGATIVE] == -1))
return 0; /* need at least one target to compare. */
if ((rc.targets[POSITIVE] != -1) &&
(rc.targets[POSITIVE]-counts[POSITIVE] == ndom))
- nonn = 1;
+ nonn = true;
if ((rc.targets[NEGATIVE] != -1) &&
(rc.targets[NEGATIVE]-counts[NEGATIVE] == ndom))
- nonn = 1;
+ nonn = true;
if (!nonn) return 0;
static char *game_state_diff(const game_state *src, const game_state *dst,
- int issolve)
+ bool issolve)
{
char *ret = NULL, buf[80], c;
int retlen = 0, x, y, i, k;
return NULL;
solved:
- move = game_state_diff(currstate, solved, 1);
+ move = game_state_diff(currstate, solved, true);
free_game(solved);
return move;
}
new->common->rowcount[y*3+val]++;
}
}
- new->numbered = 1;
+ new->numbered = true;
sfree(scratch);
}
}
struct game_ui {
- int cur_x, cur_y, cur_visible;
+ int cur_x, cur_y;
+ bool cur_visible;
};
static game_ui *new_ui(const game_state *state)
{
game_ui *ui = snew(game_ui);
ui->cur_x = ui->cur_y = 0;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
return ui;
}
const game_state *newstate)
{
if (!oldstate->completed && newstate->completed)
- ui->cur_visible = 0;
+ ui->cur_visible = false;
}
struct game_drawstate {
- int tilesize, started, solved;
+ int tilesize;
+ bool started, solved;
int w, h;
unsigned long *what; /* size w*h */
unsigned long *colwhat, *rowwhat; /* size 3*w, 3*h */
#define COORD(x) ( (x+1) * TILE_SIZE + BORDER )
#define FROMCOORD(x) ( (x - BORDER) / TILE_SIZE - 1 )
-static int is_clue(const game_state *state, int x, int y)
+static bool is_clue(const game_state *state, int x, int y)
{
int h = state->h, w = state->w;
enum { CYCLE_MAGNET, CYCLE_NEUTRAL } action;
if (IS_CURSOR_MOVE(button)) {
- move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, 0);
- ui->cur_visible = 1;
+ move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, false);
+ ui->cur_visible = true;
return UI_UPDATE;
} else if (IS_CURSOR_SELECT(button)) {
if (!ui->cur_visible) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
action = (button == CURSOR_SELECT) ? CYCLE_MAGNET : CYCLE_NEUTRAL;
} else if (INGRID(state, gx, gy) &&
(button == LEFT_BUTTON || button == RIGHT_BUTTON)) {
if (ui->cur_visible) {
- ui->cur_visible = 0;
+ ui->cur_visible = false;
nullret = UI_UPDATE;
}
action = (button == LEFT_BUTTON) ? CYCLE_MAGNET : CYCLE_NEUTRAL;
else if (*move) goto badmove;
}
if (check_completion(ret) == 1)
- ret->completed = 1;
+ ret->completed = true;
return ret;
{
struct game_drawstate *ds = snew(struct game_drawstate);
- ds->tilesize = ds->started = ds->solved = 0;
+ ds->tilesize = 0;
+ ds->started = false;
+ ds->solved = false;
ds->w = state->w;
ds->h = state->h;
int dir, const game_ui *ui,
float animtime, float flashtime)
{
- int x, y, w = state->w, h = state->h, which, i, j, flash;
+ int x, y, w = state->w, h = state->h, which, i, j;
+ bool flash;
flash = (int)(flashtime * 5 / FLASH_TIME) % 2;
}
}
- ds->started = 1;
+ ds->started = true;
}
static float game_anim_length(const game_state *oldstate,
#include <stdarg.h>
const char *quis = NULL;
-int csv = 0;
+bool csv = false;
void usage(FILE *out) {
fprintf(out, "usage: %s [-v] [--print] <params>|<game id>\n", quis);
int main(int argc, const char *argv[])
{
- int print = 0, soak = 0, solved = 0, ret;
+ bool print = false, soak = false, solved = false;
+ int ret;
char *id = NULL, *desc, *desc_gen = NULL, *aux = NULL;
const char *err;
game_state *s = NULL;
while (--argc > 0) {
char *p = (char*)(*++argv);
if (!strcmp(p, "-v") || !strcmp(p, "--verbose")) {
- verbose = 1;
+ verbose = true;
} else if (!strcmp(p, "--csv")) {
- csv = 1;
+ csv = true;
} else if (!strcmp(p, "-e") || !strcmp(p, "--seed")) {
seed = atoi(*++argv);
argc--;
} else if (!strcmp(p, "-p") || !strcmp(p, "--print")) {
- print = 1;
+ print = true;
} else if (!strcmp(p, "-s") || !strcmp(p, "--soak")) {
- soak = 1;
+ soak = true;
} else if (*p == '-') {
fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0], p);
usage(stderr);
p = default_params();
decode_params(p, id);
- err = validate_params(p, 1);
+ err = validate_params(p, true);
if (err) {
fprintf(stderr, "%s: %s", argv[0], err);
goto done;
}
if (!desc)
- desc = desc_gen = new_game_desc(p, rs, &aux, 0);
+ desc = desc_gen = new_game_desc(p, rs, &aux, false);
err = validate_desc(p, desc);
if (err) {
if (verbose || print) {
doprint(s);
solve_from_aux(s, aux);
- solved = 1;
+ solved = true;
}
} else {
doprint(s);
- verbose = 1;
+ verbose = true;
ret = solve_state(s, DIFFCOUNT);
if (ret < 0) printf("Puzzle is impossible.\n");
else if (ret == 0) printf("Puzzle is ambiguous.\n");
else printf("Puzzle was solved.\n");
- verbose = 0;
- solved = 1;
+ verbose = false;
+ solved = true;
}
if (solved) doprint(s);
*/
#if defined STANDALONE_SOLVER
#define SOLVER_DIAGNOSTICS
-int verbose = false;
+bool verbose = false;
#elif defined SOLVER_DIAGNOSTICS
#define verbose true
#endif
int *graph;
int n;
int ngraph;
- int *immutable;
+ bool *immutable;
int *edgex, *edgey; /* position of a point on each edge */
int *regionx, *regiony; /* position of a point in each region */
};
game_params p;
struct map *map;
int *colouring, *pencil;
- int completed, cheated;
+ bool completed, cheated;
};
static game_params *default_params(void)
* the sake of the Palm port and its limited stack.
*/
-static int fourcolour_recurse(int *graph, int n, int ngraph,
- int *colouring, int *scratch, random_state *rs)
+static bool fourcolour_recurse(int *graph, int n, int ngraph,
+ int *colouring, int *scratch, random_state *rs)
{
int nfree, nvert, start, i, j, k, c, ci;
int cs[FOUR];
{
int *scratch;
int i;
+ bool retd;
/*
* For each vertex and each colour, we store the number of
for (i = 0; i < n; i++)
colouring[i] = -1;
- i = fourcolour_recurse(graph, n, ngraph, colouring, scratch, rs);
- assert(i); /* by the Four Colour Theorem :-) */
+ retd = fourcolour_recurse(graph, n, ngraph, colouring, scratch, rs);
+ assert(retd); /* by the Four Colour Theorem :-) */
sfree(scratch);
}
static const char colnames[FOUR] = { 'R', 'Y', 'G', 'B' };
#endif
-static int place_colour(struct solver_scratch *sc,
- int *colouring, int index, int colour
+static bool place_colour(struct solver_scratch *sc,
+ int *colouring, int index, int colour
#ifdef SOLVER_DIAGNOSTICS
- , const char *verb
+ , const char *verb
#endif
- )
+ )
{
int *graph = sc->graph, n = sc->n, ngraph = sc->ngraph;
int j, k;
* Now repeatedly loop until we find nothing further to do.
*/
while (1) {
- int done_something = false;
+ bool done_something = false;
if (difficulty < DIFF_EASY)
break; /* can't do anything at all! */
}
if ((p & (p-1)) == 0) { /* p is a power of two */
- int c, ret;
+ int c;
+ bool ret;
for (c = 0; c < FOUR; c++)
if (p == (1 << c))
break;
int j1 = graph[i] / n, j2 = graph[i] % n;
int j, k, v, v2;
#ifdef SOLVER_DIAGNOSTICS
- int started = false;
+ bool started = false;
#endif
if (j1 > j2)
struct solver_scratch *rsc;
int *subcolouring, *origcolouring;
int ret, subret;
- int we_already_got_one;
+ bool we_already_got_one;
best = -1;
bestc = FIVE;
ret = NULL;
{
- int run, pv;
+ int run;
+ bool pv;
/*
* Start with a notional non-edge, so that there'll be an
* an edge.
*/
run = 1;
- pv = 0;
+ pv = false;
for (i = 0; i < w*(h-1) + (w-1)*h; i++) {
- int x, y, dx, dy, v;
+ int x, y, dx, dy;
+ bool v;
if (i < w*(h-1)) {
/* Horizontal edge. */
const char **desc, int *map)
{
int w = params->w, h = params->h, wh = w*h, n = params->n;
- int i, k, pos, state;
+ int i, k, pos;
+ bool state;
const char *p = *desc;
dsf_init(map+wh, wh);
pos = -1;
- state = 0;
+ state = false;
/*
* Parse the game description to get the list of edges, and
for (i = 0; i < n; i++)
state->pencil[i] = 0;
- state->completed = state->cheated = false;
+ state->completed = false;
+ state->cheated = false;
state->map = snew(struct map);
state->map->refcount = 1;
state->map->map = snewn(wh*4, int);
state->map->graph = snewn(n*n, int);
state->map->n = n;
- state->map->immutable = snewn(n, int);
+ state->map->immutable = snewn(n, bool);
for (i = 0; i < n; i++)
state->map->immutable[i] = false;
{
random_state *rs = random_new(desc, strlen(desc));
int *squares = snewn(wh, int);
- int done_something;
+ bool done_something;
for (i = 0; i < wh; i++)
squares[i] = i;
int drag_colour;
int drag_pencil;
int dragx, dragy;
- int show_numbers;
+ bool show_numbers;
- int cur_x, cur_y, cur_visible, cur_moved, cur_lastmove;
+ int cur_x, cur_y, cur_lastmove;
+ bool cur_visible, cur_moved;
};
static game_ui *new_ui(const game_state *state)
ui->drag_colour = -2;
ui->drag_pencil = 0;
ui->show_numbers = false;
- ui->cur_x = ui->cur_y = ui->cur_visible = ui->cur_moved = 0;
+ ui->cur_x = ui->cur_y = 0;
+ ui->cur_visible = false;
+ ui->cur_moved = false;
ui->cur_lastmove = 0;
return ui;
}
struct game_drawstate {
int tilesize;
unsigned long *drawn, *todraw;
- int started;
- int dragx, dragy, drag_visible;
+ bool started;
+ int dragx, dragy;
+ bool drag_visible;
blitter *bl;
};
int x, int y, int button)
{
char *bufp, buf[256];
- int alt_button, drop_region;
+ bool alt_button;
+ int drop_region;
/*
* Enable or disable numeric labels on regions.
}
if (IS_CURSOR_MOVE(button)) {
- move_cursor(button, &ui->cur_x, &ui->cur_y, state->p.w, state->p.h, 0);
- ui->cur_visible = 1;
- ui->cur_moved = 1;
+ move_cursor(button, &ui->cur_x, &ui->cur_y, state->p.w, state->p.h,
+ false);
+ ui->cur_visible = true;
+ ui->cur_moved = true;
ui->cur_lastmove = button;
return UI_UPDATE;
}
if (IS_CURSOR_SELECT(button)) {
if (!ui->cur_visible) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
if (ui->drag_colour == -2) { /* not currently cursor-dragging, start. */
ui->drag_colour = -1;
ui->drag_pencil = 0;
}
- ui->cur_moved = 0;
+ ui->cur_moved = false;
return UI_UPDATE;
} else { /* currently cursor-dragging; drop the colour in the new region. */
- alt_button = (button == CURSOR_SELECT2) ? 1 : 0;
+ alt_button = (button == CURSOR_SELECT2);
/* Double-select removes current colour. */
if (!ui->cur_moved) ui->drag_colour = -1;
drop_region = region_from_ui_cursor(state, ui);
}
ui->dragx = x;
ui->dragy = y;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
return UI_UPDATE;
}
if ((button == LEFT_RELEASE || button == RIGHT_RELEASE) &&
ui->drag_colour > -2) {
- alt_button = (button == RIGHT_RELEASE) ? 1 : 0;
+ alt_button = (button == RIGHT_RELEASE);
drop_region = region_from_coords(state, ds, x, y);
goto drag_dropped;
}
int c, k, adv, i;
while (*move) {
- int pencil = false;
+ bool pencil = false;
c = *move;
if (c == 'p') {
* Check for completion.
*/
if (!ret->completed) {
- int ok = true;
+ bool ok = true;
for (i = 0; i < n; i++)
if (ret->colouring[i] < 0) {
* Draw the dragged colour blob if any.
*/
if ((ui->drag_colour > -2) || ui->cur_visible) {
- int bg, iscur = 0, cursor_x, cursor_y;
+ int bg, cursor_x, cursor_y;
+ bool iscur = false;
if (ui->drag_colour >= 0)
bg = COL_0 + ui->drag_colour;
else if (ui->drag_colour == -1) {
int c = (r < 0) ? -1 : state->colouring[r];
/*bg = COL_GRID;*/
bg = (c < 0) ? COL_BACKGROUND : COL_0 + c;
- iscur = 1;
+ iscur = true;
}
if (ui->cur_visible) {
game_state *s;
char *id = NULL, *desc;
const char *err;
- int grade = false;
- int ret, diff, really_verbose = false;
+ bool grade = false;
+ int ret, diff;
+ bool really_verbose = false;
struct solver_scratch *sc;
int i;
layer = 0;
while (1) {
- int found_free_R_vertex = false;
+ bool found_free_R_vertex = false;
Rqs = 0;
for (i = 0; i < Lqs; i++) {
{
static const char stdin_identifier[] = "<standard input>";
const char *infile = NULL;
- int doing_opts = true;
+ bool doing_opts = true;
enum { USER_INPUT, AUTOTEST } mode = USER_INPUT;
while (--argc > 0) {
struct midend_state_entry *states;
struct midend_serialise_buf newgame_undo, newgame_redo;
- int newgame_can_store_undo;
+ bool newgame_can_store_undo;
game_params *params, *curparams;
game_drawstate *drawstate;
float flash_time, flash_pos;
int dir;
- int timing;
+ bool timing;
float elapsed;
char *laststatus;
}
struct newgame_undo_deserialise_check_ctx {
- int refused;
+ bool refused;
};
static const char *newgame_undo_deserialise_check(
return NULL;
}
-static int midend_undo(midend *me)
+static bool midend_undo(midend *me)
{
const char *deserialise_error;
me->states[me->statepos-2].state);
me->statepos--;
me->dir = -1;
- return 1;
+ return true;
} else if (me->newgame_undo.len) {
struct newgame_undo_deserialise_read_ctx rctx;
struct newgame_undo_deserialise_check_ctx cctx;
* function, which we ignore.)
*/
sfree(serbuf.buf);
- return 0;
+ return false;
} else {
/*
* There should never be any _other_ deserialisation
newgame_serialise_write(&me->newgame_redo, serbuf.buf, serbuf.len);
sfree(serbuf.buf);
- return 1;
+ return true;
}
} else
- return 0;
+ return false;
}
-static int midend_redo(midend *me)
+static bool midend_redo(midend *me)
{
const char *deserialise_error;
me->states[me->statepos].state);
me->statepos++;
me->dir = +1;
- return 1;
+ return true;
} else if (me->newgame_redo.len) {
struct newgame_undo_deserialise_read_ctx rctx;
struct newgame_undo_deserialise_check_ctx cctx;
* function, which we ignore.)
*/
sfree(serbuf.buf);
- return 0;
+ return false;
} else {
/*
* There should never be any _other_ deserialisation
newgame_serialise_write(&me->newgame_undo, serbuf.buf, serbuf.len);
sfree(serbuf.buf);
- return 1;
+ return true;
}
} else
- return 0;
+ return false;
}
static void midend_finish_move(midend *me)
{
game_state *oldstate =
me->ourgame->dup_game(me->states[me->statepos - 1].state);
- int type = MOVE, gottype = false, ret = true;
+ int type = MOVE;
+ bool gottype = false, ret = true;
float anim_time;
game_state *s;
char *movestr = NULL;
void midend_timer(midend *me, float tplus)
{
- int need_redraw = (me->anim_time > 0 || me->flash_time > 0);
+ bool need_redraw = (me->anim_time > 0 || me->flash_time > 0);
me->anim_pos += tplus;
if (me->anim_pos >= me->anim_time ||
}
static char *preset_menu_add_from_user_env(
- midend *me, struct preset_menu *menu, char *p, int top_level)
+ midend *me, struct preset_menu *menu, char *p, bool top_level)
{
while (*p) {
char *name, *val;
char *par = NULL;
const char *desc, *seed;
game_params *newcurparams, *newparams, *oldparams1, *oldparams2;
- int free_params;
+ bool free_params;
seed = strchr(id, '#');
desc = strchr(id, ':');
{
struct deserialise_data data;
int gotstates = 0;
- int started = false;
+ bool started = false;
int i;
char *val = NULL;
void *rctx)
{
int nstates = 0, statepos = -1, gotstates = 0;
- int started = false;
+ bool started = false;
char *val = NULL;
/* Initially all errors give the same report */
struct game_params {
int w, h, n;
- int unique;
+ bool unique;
};
struct mine_layout {
* given instance of the puzzle, so we reference-count it.
*/
int refcount;
- char *mines;
+ bool *mines;
/*
* If we haven't yet actually generated the mine layout, here's
* all the data we will need to do so.
*/
- int n, unique;
+ int n;
+ bool unique;
random_state *rs;
midend *me; /* to give back the new game desc */
};
struct game_state {
- int w, h, n, dead, won;
- int used_solve;
+ int w, h, n;
+ bool dead, won, used_solve;
struct mine_layout *layout; /* real mine positions */
signed char *grid; /* player knowledge */
/*
*/
struct set {
short x, y, mask, mines;
- int todo;
+ bool todo;
struct set *prev, *next;
};
* with the second. Return the new mask part of the first set.
*/
static int setmunge(int x1, int y1, int mask1, int x2, int y2, int mask2,
- int diff)
+ bool diff)
{
/*
* Adjust the second set so that it has the same x,y
static void known_squares(int w, int h, struct squaretodo *std,
signed char *grid,
open_cb open, void *openctx,
- int x, int y, int mask, int mine)
+ int x, int y, int mask, bool mine)
{
int xx, yy, bit;
* Main deductive loop.
*/
while (1) {
- int done_something = false;
+ bool done_something = false;
struct set *s;
/*
*/
int minesleft, squaresleft;
- int nsets, setused[10], cursor;
+ int nsets, cursor;
+ bool setused[10];
/*
* Start by scanning the current grid state to work out
* I'm going to use a virtual recursion within this
* function. The way this works is:
*
- * - we have an array `setused', such that
- * setused[n] is 0 or 1 depending on whether set
- * n is currently in the union we are
- * considering.
+ * - we have an array `setused', such that setused[n]
+ * is true if set n is currently in the union we
+ * are considering.
*
* - we have a value `cursor' which indicates how
* much of `setused' we have so far filled in.
*
* We begin by setting `cursor' to zero. Then:
*
- * - if cursor can advance, we advance it by one.
- * We set the value in `setused' that it went
- * past to 1 if that set is disjoint from
- * anything else currently in `setused', or to 0
- * otherwise.
+ * - if cursor can advance, we advance it by one. We
+ * set the value in `setused' that it went past to
+ * true if that set is disjoint from anything else
+ * currently in `setused', or to false otherwise.
*
* - If cursor cannot advance because it has
* reached the end of the setused list, then we
* properties. If so, mark all the squares not
* in the union as known and terminate.
*
- * - If cursor has reached the end of setused and
- * the algorithm _hasn't_ terminated, back
- * cursor up to the nearest 1, turn it into a 0
- * and advance cursor just past it.
+ * - If cursor has reached the end of setused and the
+ * algorithm _hasn't_ terminated, back cursor up to
+ * the nearest true entry, reset it to false, and
+ * advance cursor just past it.
*
* - If we attempt to back up to the nearest 1 and
* there isn't one at all, then we have gone
while (1) {
if (cursor < nsets) {
- int ok = true;
+ bool ok = true;
/* See if any existing set overlaps this one. */
for (i = 0; i < cursor; i++)
*/
for (i = 0; i < w*h; i++)
if (grid[i] == -2) {
- int outside = true;
+ bool outside = true;
y = i / w;
x = i % w;
for (j = 0; j < nsets; j++)
minesleft += sets[cursor]->mines;
squaresleft += bitcount16(sets[cursor]->mask);
- setused[cursor++] = 0;
+ setused[cursor++] = false;
} else {
/*
* We've backtracked all the way to the
*/
struct minectx {
- char *grid;
+ bool *grid;
int w, h;
int sx, sy;
- int allow_big_perturbs;
+ bool allow_big_perturbs;
random_state *rs;
};
return ret;
}
-static char *minegen(int w, int h, int n, int x, int y, int unique,
+static bool *minegen(int w, int h, int n, int x, int y, bool unique,
random_state *rs)
{
- char *ret = snewn(w*h, char);
- int success;
+ bool *ret = snewn(w*h, bool);
+ bool success;
int ntries = 0;
do {
nn = n;
while (nn-- > 0) {
i = random_upto(rs, k);
- ret[tmp[i]] = 1;
+ ret[tmp[i]] = true;
tmp[i] = tmp[--k];
}
return ret;
}
-static char *describe_layout(char *grid, int area, int x, int y,
- int obfuscate)
+static char *describe_layout(bool *grid, int area, int x, int y,
+ bool obfuscate)
{
char *ret, *p;
unsigned char *bmp;
return ret;
}
-static char *new_mine_layout(int w, int h, int n, int x, int y, int unique,
+static bool *new_mine_layout(int w, int h, int n, int x, int y, bool unique,
random_state *rs, char **game_desc)
{
- char *grid;
+ bool *grid;
#ifdef TEST_OBFUSCATION
static int tested_obfuscation = false;
/*
* For batch-generated grids, pre-open one square.
*/
- char *grid;
+ bool *grid;
char *desc;
grid = new_mine_layout(params->w, params->h, params->n,
* using repeated N^2 scans of the grid.
*/
while (1) {
- int done_something = false;
+ bool done_something = false;
for (yy = 0; yy < h; yy++)
for (xx = 0; xx < w; xx++)
const char *desc)
{
game_state *state = snew(game_state);
- int i, wh, x, y, masked;
+ int i, wh, x, y;
+ bool masked;
unsigned char *bmp;
state->w = params->w;
} else {
state->layout->rs = NULL;
state->layout->me = NULL;
- state->layout->mines = snewn(wh, char);
+ state->layout->mines = snewn(wh, bool);
if (*desc && isdigit((unsigned char)*desc)) {
x = atoi(desc);
if (masked)
obfuscate_bitmap(bmp, wh, true);
- memset(state->layout->mines, 0, wh);
+ memset(state->layout->mines, 0, wh * sizeof(bool));
for (i = 0; i < wh; i++) {
if (bmp[i / 8] & (0x80 >> (i % 8)))
- state->layout->mines[i] = 1;
+ state->layout->mines[i] = true;
}
if (x >= 0 && y >= 0)
struct game_ui {
int hx, hy, hradius; /* for mouse-down highlights */
int validradius;
- int flash_is_death;
- int deaths, completed;
- int cur_x, cur_y, cur_visible;
+ bool flash_is_death;
+ int deaths;
+ bool completed;
+ int cur_x, cur_y;
+ bool cur_visible;
};
static game_ui *new_ui(const game_state *state)
ui->deaths = 0;
ui->completed = false;
ui->flash_is_death = false; /* *shrug* */
- ui->cur_x = ui->cur_y = ui->cur_visible = 0;
+ ui->cur_x = ui->cur_y = 0;
+ ui->cur_visible = false;
return ui;
}
}
struct game_drawstate {
- int w, h, started, tilesize, bg;
+ int w, h, tilesize, bg;
+ bool started;
signed char *grid;
/*
* Items in this `grid' array have all the same values as in
cy = FROMCOORD(y);
if (IS_CURSOR_MOVE(button)) {
- move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, 0);
- ui->cur_visible = 1;
+ move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, false);
+ ui->cur_visible = true;
return UI_UPDATE;
}
if (IS_CURSOR_SELECT(button)) {
int v = from->grid[ui->cur_y * from->w + ui->cur_x];
if (!ui->cur_visible) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
if (button == CURSOR_SELECT2) {
ui->validradius = ui->hradius;
else if (button == MIDDLE_BUTTON)
ui->validradius = 1;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
return UI_UPDATE;
}
{
int x, y;
int mines, markers, closed, bg;
- int cx = -1, cy = -1, cmoved;
+ int cx = -1, cy = -1;
+ bool cmoved;
if (flashtime) {
int frame = (int)(flashtime / FLASH_FRAME);
mines = markers = closed = 0;
for (y = 0; y < ds->h; y++)
for (x = 0; x < ds->w; x++) {
- int v = state->grid[y*ds->w+x], cc = 0;
+ int v = state->grid[y*ds->w+x];
+ bool cc = false;
if (v < 0)
closed++;
if (cmoved && /* if cursor has moved, force redraw of curr and prev pos */
((x == cx && y == cy) || (x == ds->cur_x && y == ds->cur_y)))
- cc = 1;
+ cc = true;
if (ds->grid[y*ds->w+x] != v || bg != ds->bg || cc) {
draw_tile(dr, ds, COORD(x), COORD(y), v,
struct frontend {
// TODO kill unneeded members!
midend *me;
- int timer_active;
+ bool timer_active;
struct timeval last_time;
config_item *cfg;
- int cfg_which, cfgret;
+ int cfg_which;
+ bool cfgret;
int ox, oy, w, h;
};
i->u.choices.selected = selected;
}
-static int get_config(frontend *fe, int which)
+static bool get_config(frontend *fe, int which)
{
char *title;
config_item *i;
struct game_params {
int width;
int height;
- int wrapping;
- int unique;
+ bool wrapping;
+ bool unique;
float barrier_probability;
};
} game_immutable_state;
struct game_state {
- int width, height, wrapping, completed;
+ int width, height;
+ bool wrapping, completed;
int last_rotate_x, last_rotate_y, last_rotate_dir;
- int used_solve;
+ bool used_solve;
unsigned char *tiles;
struct game_immutable_state *imm;
};
*/
struct todo {
- unsigned char *marked;
+ bool *marked;
int *buffer;
int buflen;
int head, tail;
static struct todo *todo_new(int maxsize)
{
struct todo *todo = snew(struct todo);
- todo->marked = snewn(maxsize, unsigned char);
+ todo->marked = snewn(maxsize, bool);
memset(todo->marked, 0, maxsize);
todo->buflen = maxsize + 1;
todo->buffer = snewn(todo->buflen, int);
* fully.
*/
static int net_solver(int w, int h, unsigned char *tiles,
- unsigned char *barriers, int wrapping)
+ unsigned char *barriers, bool wrapping)
{
unsigned char *tilestate;
unsigned char *edgestate;
struct todo *todo;
int i, j, x, y;
int area;
- int done_something;
+ bool done_something;
/*
* Set up the solver's data structures.
deadendmax[1] = deadendmax[2] = deadendmax[4] = deadendmax[8] = 0;
for (i = j = 0; i < 4 && tilestate[(y*w+x) * 4 + i] != 255; i++) {
- int valid;
+ bool valid;
int nnondeadends, nondeadends[4], deadendtotal;
int nequiv, equiv[5];
int val = tilestate[(y*w+x) * 4 + i];
* Function to randomly perturb an ambiguous section in a grid, to
* attempt to ensure unique solvability.
*/
-static void perturb(int w, int h, unsigned char *tiles, int wrapping,
+static void perturb(int w, int h, unsigned char *tiles, bool wrapping,
random_state *rs, int startx, int starty, int startd)
{
struct xyd *perimeter, *perim2, *loop[2], looppos[2];
sfree(perimeter);
}
-static int *compute_loops_inner(int w, int h, int wrapping,
+static int *compute_loops_inner(int w, int h, bool wrapping,
const unsigned char *tiles,
const unsigned char *barriers);
return -1;
}
-static int *compute_loops_inner(int w, int h, int wrapping,
+static int *compute_loops_inner(int w, int h, bool wrapping,
const unsigned char *tiles,
const unsigned char *barriers)
{
int org_x, org_y; /* origin */
int cx, cy; /* source tile (game coordinates) */
int cur_x, cur_y;
- int cur_visible;
+ bool cur_visible;
random_state *rs; /* used for jumbling */
#ifdef USE_DRAGGING
- int dragtilex, dragtiley, dragstartx, dragstarty, dragged;
+ int dragtilex, dragtiley, dragstartx, dragstarty;
+ bool dragged;
#endif
};
}
struct game_drawstate {
- int started;
+ bool started;
int width, height;
int tilesize;
unsigned long *visible, *to_draw;
{
char *nullret;
int tx = -1, ty = -1, dir = 0;
- int shift = button & MOD_SHFT, ctrl = button & MOD_CTRL;
+ bool shift = button & MOD_SHFT, ctrl = button & MOD_CTRL;
enum {
NONE, ROTATE_LEFT, ROTATE_180, ROTATE_RIGHT, TOGGLE_LOCK, JUMBLE,
MOVE_ORIGIN, MOVE_SOURCE, MOVE_ORIGIN_AND_SOURCE, MOVE_CURSOR
static game_state *execute_move(const game_state *from, const char *move)
{
game_state *ret;
- int tx = -1, ty = -1, n, noanim, orig;
+ int tx = -1, ty = -1, n, orig;
+ bool noanim;
ret = dup_game(from);
{
unsigned char *active;
int pos;
- int complete = true;
+ bool complete = true;
for (pos = 0; pos < ret->width * ret->height; pos++)
if (ret->tiles[pos] & 0xF)
float fpoints[12*2];
int points[12*2];
int npoints, d, dsh, i;
- int any_wire_this_colour = false;
+ bool any_wire_this_colour = false;
float xf, yf;
npoints = 0;
{
char statusbuf[256], *p;
int i, n, n2, a;
- int complete = false;
+ bool complete = false;
p = statusbuf;
*p = '\0'; /* ensure even an empty status string is terminated */
}
static void draw_diagram(drawing *dr, game_drawstate *ds, int x, int y,
- int topleft, int v, int drawlines, int ink)
+ bool topleft, int v, bool drawlines, int ink)
{
int tx, ty, cx, cy, r, br, k, thick;
struct game_params {
int width;
int height;
- int wrapping;
+ bool wrapping;
float barrier_probability;
int movetarget;
};
struct game_state {
- int width, height, cx, cy, wrapping, completed;
- int used_solve;
+ int width, height, cx, cy, completed;
+ bool wrapping, used_solve;
int move_count, movetarget;
/* position (row or col number, starting at 0) of last move. */
p++;
ret->height = atoi(p);
while (*p && isdigit((unsigned char)*p)) p++;
- if ( (ret->wrapping = (*p == 'w')) != 0 )
+ ret->wrapping = (*p == 'w');
+ if (ret->wrapping)
p++;
if (*p == 'b') {
ret->barrier_probability = (float)atof(++p);
for (dir = 1; dir < 0x10; dir <<= 1) {
int dir2 = A(dir);
int x1, y1, x2, y2, x3, y3;
- int corner = false;
+ bool corner = false;
if (!(barrier(state, x, y) & dir))
continue;
struct game_ui {
int cur_x, cur_y;
- int cur_visible;
+ bool cur_visible;
};
static game_ui *new_ui(const game_state *state)
}
struct game_drawstate {
- int started;
+ bool started;
int width, height;
int tilesize;
unsigned char *visible;
} while (ui->cur_x == state->cx || ui->cur_y == state->cy);
}
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
cx = (x - (BORDER + WINDOW_OFFSET + TILE_BORDER) + 2*TILE_SIZE) / TILE_SIZE - 2;
cy = (y - (BORDER + WINDOW_OFFSET + TILE_BORDER) + 2*TILE_SIZE) / TILE_SIZE - 2;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
} else if (IS_CURSOR_SELECT(button)) {
if (ui->cur_visible) {
cx = ui->cur_x;
cy = ui->cur_y;
} else {
/* 'click' when cursor is invisible just makes cursor visible. */
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
} else
static game_state *execute_move(const game_state *from, const char *move)
{
game_state *ret;
- int c, d, col;
+ int c, d;
+ bool col;
if ((move[0] == 'C' || move[0] == 'R') &&
sscanf(move+1, "%d,%d", &c, &d) == 2 &&
if (!ret->completed) {
unsigned char *active = compute_active(ret, -1, -1);
int x1, y1;
- int complete = true;
+ bool complete = true;
for (x1 = 0; x1 < ret->width; x1++)
for (y1 = 0; y1 < ret->height; y1++)
}
static void draw_arrow(drawing *dr, game_drawstate *ds,
- int x, int y, int xdx, int xdy, int cur)
+ int x, int y, int xdx, int xdy, bool cur)
{
int coords[14];
int ydy = -xdx, ydx = xdy;
}
static void draw_arrow_for_cursor(drawing *dr, game_drawstate *ds,
- int cur_x, int cur_y, int cur)
+ int cur_x, int cur_y, bool cur)
{
if (cur_x == -1 && cur_y == -1)
return; /* 'no cursur here */
*/
for (x = 0; x < ds->width; x++) {
if (x == state->cx) continue;
- draw_arrow(dr, ds, x, 0, +1, 0, 0);
- draw_arrow(dr, ds, x+1, ds->height, -1, 0, 0);
+ draw_arrow(dr, ds, x, 0, +1, 0, false);
+ draw_arrow(dr, ds, x+1, ds->height, -1, 0, false);
}
for (y = 0; y < ds->height; y++) {
if (y == state->cy) continue;
- draw_arrow(dr, ds, ds->width, y, 0, +1, 0);
- draw_arrow(dr, ds, 0, y+1, 0, -1, 0);
+ draw_arrow(dr, ds, ds->width, y, 0, +1, false);
+ draw_arrow(dr, ds, 0, y+1, 0, -1, false);
}
}
if (ui->cur_visible) {
/* Cursor has changed; redraw two (prev and curr) arrows. */
assert(cur_x != state->cx && cur_y != state->cy);
- draw_arrow_for_cursor(dr, ds, cur_x, cur_y, 1);
- draw_arrow_for_cursor(dr, ds, ds->cur_x, ds->cur_y, 0);
+ draw_arrow_for_cursor(dr, ds, cur_x, cur_y, true);
+ draw_arrow_for_cursor(dr, ds, ds->cur_x, ds->cur_y, false);
ds->cur_x = cur_x; ds->cur_y = cur_y;
}
char *inhex = NULL;
unsigned char *data;
int datalen;
- int decode = -1;
- int doing_opts = true;
+ enum { UNKNOWN, DECODE, ENCODE } mode = UNKNOWN;
+ bool doing_opts = true;
while (--argc > 0) {
char *p = *++argv;
while (*p) {
switch (*p) {
case 'e':
- decode = 0;
+ mode = ENCODE;
break;
case 'd':
- decode = 1;
+ mode = DECODE;
break;
case 'b':
outputmode = BINARY;
}
}
- if (decode < 0) {
+ if (mode == UNKNOWN) {
fprintf(stderr, "usage: obfusc < -e | -d > [ -b | -h ] [hex data]\n");
return 0;
}
if (outputmode == DEFAULT)
- outputmode = (decode ? BINARY : HEX);
+ outputmode = (mode == DECODE ? BINARY : HEX);
if (inhex) {
datalen = strlen(inhex) / 2;
}
}
- obfuscate_bitmap(data, datalen * 8, decode);
+ obfuscate_bitmap(data, datalen * 8, mode == DECODE);
if (outputmode == BINARY) {
int ret = fwrite(data, 1, datalen, stdout);
MyImageView *view;
NSColor **colours;
int ncolours;
- int clipped;
+ bool clipped;
int w, h;
};
frame.origin.x = 0;
w = h = INT_MAX;
- midend_size(me, &w, &h, FALSE);
+ midend_size(me, &w, &h, false);
frame.size.width = w;
frame.size.height = h;
fe.w = w;
*/
midend_new_game(me);
w = h = INT_MAX;
- midend_size(me, &w, &h, FALSE);
+ midend_size(me, &w, &h, false);
rect.size.width = w;
rect.size.height = h;
fe.w = w;
* function key codes.
*/
if (c >= 0x80) {
- int mods = FALSE;
+ bool mods = false;
switch (c) {
case NSUpArrowFunctionKey:
c = CURSOR_UP;
- mods = TRUE;
+ mods = true;
break;
case NSDownArrowFunctionKey:
c = CURSOR_DOWN;
- mods = TRUE;
+ mods = true;
break;
case NSLeftArrowFunctionKey:
c = CURSOR_LEFT;
- mods = TRUE;
+ mods = true;
break;
case NSRightArrowFunctionKey:
c = CURSOR_RIGHT;
- mods = TRUE;
+ mods = true;
break;
default:
continue;
int w, h;
w = h = INT_MAX;
- midend_size(me, &w, &h, FALSE);
+ midend_size(me, &w, &h, false);
size.width = w;
size.height = h;
fe.w = w;
[self startConfigureSheet:CFG_SETTINGS];
}
-- (void)sheetEndWithStatus:(BOOL)update
+- (void)sheetEndWithStatus:(bool)update
{
assert(sheet != NULL);
[app endSheet:sheet];
}
- (void)sheetOKButton:(id)sender
{
- [self sheetEndWithStatus:YES];
+ [self sheetEndWithStatus:true];
}
- (void)sheetCancelButton:(id)sender
{
- [self sheetEndWithStatus:NO];
+ [self sheetEndWithStatus:false];
}
- (void)setStatusLine:(const char *)text
if (!fe->clipped)
[[NSGraphicsContext currentContext] saveGraphicsState];
[NSBezierPath clipRect:r];
- fe->clipped = TRUE;
+ fe->clipped = true;
}
static void osx_unclip(void *handle)
{
frontend *fe = (frontend *)handle;
if (fe->clipped)
[[NSGraphicsContext currentContext] restoreGraphicsState];
- fe->clipped = FALSE;
+ fe->clipped = false;
}
static void osx_start_draw(void *handle)
{
frontend *fe = (frontend *)handle;
[fe->image lockFocus];
- fe->clipped = FALSE;
+ fe->clipped = false;
}
static void osx_end_draw(void *handle)
{
shared_state *shared;
borderflag *borders; /* length w*h */
- unsigned int completed: 1;
- unsigned int cheated: 1;
+ bool completed, cheated;
};
#define DEFAULT_PRESET 0
dsf_merge(ctx->dsf, i, j);
}
-static int connected(solver_ctx *ctx, int i, int j, int dir)
+static bool connected(solver_ctx *ctx, int i, int j, int dir)
{
if (j == COMPUTE_J) j = i + dx[dir] + ctx->params->w*dy[dir];
return dsf_canonify(ctx->dsf, i) == dsf_canonify(ctx->dsf, j);
ctx->borders[j] |= BORDER(FLIP(dir));
}
-static int disconnected(solver_ctx *ctx, int i, int j, int dir)
+static bool disconnected(solver_ctx *ctx, int i, int j, int dir)
{
assert (j == COMPUTE_J || j == i + dx[dir] + ctx->params->w*dy[dir]);
return ctx->borders[i] & BORDER(dir);
}
-static int maybe(solver_ctx *ctx, int i, int j, int dir)
+static bool maybe(solver_ctx *ctx, int i, int j, int dir)
{
assert (j == COMPUTE_J || j == i + dx[dir] + ctx->params->w*dy[dir]);
return !disconnected(ctx, i, j, dir) && !connected(ctx, i, j, dir);
}
}
-static int solver_number_exhausted(solver_ctx *ctx)
+static bool solver_number_exhausted(solver_ctx *ctx)
{
int w = ctx->params->w, h = ctx->params->h, wh = w*h, i, dir, off;
- int changed = false;
+ bool changed = false;
for (i = 0; i < wh; ++i) {
if (ctx->clues[i] == EMPTY) continue;
return changed;
}
-static int solver_not_too_big(solver_ctx *ctx)
+static bool solver_not_too_big(solver_ctx *ctx)
{
int w = ctx->params->w, h = ctx->params->h, wh = w*h, i, dir;
- int changed = false;
+ bool changed = false;
for (i = 0; i < wh; ++i) {
int size = dsf_size(ctx->dsf, i);
return changed;
}
-static int solver_not_too_small(solver_ctx *ctx)
+static bool solver_not_too_small(solver_ctx *ctx)
{
int w = ctx->params->w, h = ctx->params->h, wh = w*h, i, dir;
- int *outs, k = ctx->params->k, ci, changed = false;
+ int *outs, k = ctx->params->k, ci;
+ bool changed = false;
snewa(outs, wh);
setmem(outs, -1, wh);
return changed;
}
-static int solver_no_dangling_edges(solver_ctx *ctx)
+static bool solver_no_dangling_edges(solver_ctx *ctx)
{
int w = ctx->params->w, h = ctx->params->h, r, c;
- int changed = false;
+ bool changed = false;
/* for each vertex */
for (r = 1; r < h; ++r)
return changed;
}
-static int solver_equivalent_edges(solver_ctx *ctx)
+static bool solver_equivalent_edges(solver_ctx *ctx)
{
int w = ctx->params->w, h = ctx->params->h, wh = w*h, i, dirj;
- int changed = false;
+ bool changed = false;
/* if a square is adjacent to two connected squares, the two
* borders (i,j) and (i,k) are either both on or both off. */
#define UNVISITED 6
/* build connected components in `dsf', along the lines of `borders'. */
-static void dfs_dsf(int i, int w, borderflag *border, int *dsf, int black)
+static void dfs_dsf(int i, int w, borderflag *border, int *dsf, bool black)
{
int dir;
for (dir = 0; dir < 4; ++dir) {
}
}
-static int is_solved(const game_params *params, clue *clues,
- borderflag *border)
+static bool is_solved(const game_params *params, clue *clues,
+ borderflag *border)
{
int w = params->w, h = params->h, wh = w*h, k = params->k;
int i, x, y;
return false;
}
-static int solver(const game_params *params, clue *clues, borderflag *borders)
+static bool solver(const game_params *params, clue *clues, borderflag *borders)
{
- int w = params->w, h = params->h, wh = w*h, changed;
+ int w = params->w, h = params->h, wh = w*h;
+ bool changed;
solver_ctx ctx;
ctx.params = params;
struct game_ui {
int x, y;
- unsigned int show: 1;
+ bool show;
};
static game_ui *new_ui(const game_state *state)
const game_drawstate *ds, int x, int y, int button)
{
int w = state->shared->params.w, h = state->shared->params.h;
- int control = button & MOD_CTRL, shift = button & MOD_SHFT;
+ bool control = button & MOD_CTRL, shift = button & MOD_SHFT;
button &= ~MOD_MASK;
static bool game_timing_state(const game_state *state, game_ui *ui)
{
assert (!"this shouldn't get called");
- return 0; /* placate optimiser */
+ return false; /* placate optimiser */
}
static void game_print_size(const game_params *params, float *x, float *y)
}
static void print_line(drawing *dr, int x1, int y1, int x2, int y2,
- int colour, int full)
+ int colour, bool full)
{
if (!full) {
int i, subdivisions = 8;
int w, h;
int rowsize;
int *rowdata, *rowlen;
- unsigned char *immutable;
+ bool *immutable;
int refcount;
} game_state_common;
struct game_state {
game_state_common *common;
unsigned char *grid;
- int completed, cheated;
+ bool completed, cheated;
};
#define FLASH_TIME 0.13F
#define STILL_UNKNOWN 3
#ifdef STANDALONE_SOLVER
-int verbose = false;
+bool verbose = false;
#endif
-static int do_recurse(unsigned char *known, unsigned char *deduced,
+static bool do_recurse(unsigned char *known, unsigned char *deduced,
unsigned char *row,
unsigned char *minpos_done, unsigned char *maxpos_done,
unsigned char *minpos_ok, unsigned char *maxpos_ok,
}
-static int do_row(unsigned char *known, unsigned char *deduced,
- unsigned char *row,
- unsigned char *minpos_done, unsigned char *maxpos_done,
- unsigned char *minpos_ok, unsigned char *maxpos_ok,
- unsigned char *start, int len, int step, int *data,
- unsigned int *changed
+static bool do_row(unsigned char *known, unsigned char *deduced,
+ unsigned char *row,
+ unsigned char *minpos_done, unsigned char *maxpos_done,
+ unsigned char *minpos_ok, unsigned char *maxpos_ok,
+ unsigned char *start, int len, int step, int *data,
+ unsigned int *changed
#ifdef STANDALONE_SOLVER
- , const char *rowcol, int index, int cluewid
+ , const char *rowcol, int index, int cluewid
#endif
- )
+ )
{
- int rowlen, i, freespace, done_any;
+ int rowlen, i, freespace;
+ bool done_any;
freespace = len+1;
for (rowlen = 0; data[rowlen]; rowlen++) {
return done_any;
}
-static int solve_puzzle(const game_state *state, unsigned char *grid,
- int w, int h,
- unsigned char *matrix, unsigned char *workspace,
- unsigned int *changed_h, unsigned int *changed_w,
- int *rowdata
+static bool solve_puzzle(const game_state *state, unsigned char *grid,
+ int w, int h,
+ unsigned char *matrix, unsigned char *workspace,
+ unsigned int *changed_h, unsigned int *changed_w,
+ int *rowdata
#ifdef STANDALONE_SOLVER
- , int cluewid
+ , int cluewid
#else
- , int dummy
+ , int dummy
#endif
- )
+ )
{
- int i, j, ok, max;
+ int i, j, max;
+ bool ok;
int max_h, max_w;
assert((state!=NULL && state->common->rowdata!=NULL) ^ (grid!=NULL));
#ifndef STANDALONE_PICTURE_GENERATOR
static unsigned char *generate_soluble(random_state *rs, int w, int h)
{
- int i, j, ok, ntries, max;
+ int i, j, ntries, max;
+ bool ok;
unsigned char *grid, *matrix, *workspace;
unsigned int *changed_h, *changed_w;
int *rowdata;
state->grid = grid;
state->common = snew(game_state_common);
state->common->rowdata = NULL;
- state->common->immutable = snewn(params->w * params->h, unsigned char);
- memset(state->common->immutable, 1, params->w * params->h);
+ state->common->immutable = snewn(params->w * params->h, bool);
+ for (i = 0; i < params->w * params->h; i++)
+ state->common->immutable[i] = true;
index = snewn(params->w * params->h, int);
for (i = 0; i < params->w * params->h; i++)
unsigned int *changed_w = snewn(max+1, unsigned int);
int *rowdata = snewn(max+1, int);
for (i = 0; i < params->w * params->h; i++) {
- state->common->immutable[index[i]] = 0;
+ state->common->immutable[index[i]] = false;
if (!solve_puzzle(state, grid, params->w, params->h,
matrix, workspace, changed_h, changed_w,
rowdata, 0))
- state->common->immutable[index[i]] = 1;
+ state->common->immutable[index[i]] = true;
}
sfree(workspace);
sfree(changed_h);
memset(state->grid, GRID_UNKNOWN, state->common->w * state->common->h);
state->common->immutable = snewn(state->common->w * state->common->h,
- unsigned char);
- memset(state->common->immutable, 0, state->common->w * state->common->h);
+ bool);
+ memset(state->common->immutable, 0,
+ state->common->w * state->common->h * sizeof(bool));
state->common->rowsize = max(state->common->w, state->common->h);
state->common->rowdata = snewn(state->common->rowsize * (state->common->w + state->common->h), int);
i = 0;
while (i < params->w * params->h) {
int c = (unsigned char)*desc++;
- int full = isupper(c), len = tolower(c) - 'a';
+ bool full = isupper(c);
+ int len = tolower(c) - 'a';
i += len;
if (len < 25 && i < params->w*params->h) {
state->grid[i] = full ? GRID_FULL : GRID_EMPTY;
int w = state->common->w, h = state->common->h;
int i;
char *ret;
- int max, ok;
+ int max;
+ bool ok;
unsigned char *workspace;
unsigned int *changed_h, *changed_w;
int *rowdata;
}
}
for (i = 0; i < h; ++i) {
- int rowlen = 0, predecessors = false;
+ int rowlen = 0;
+ bool predecessors = false;
for (j = 0; j < state->common->rowlen[i+w]; ++j) {
int copy = state->common->rowdata[(i+w)*state->common->rowsize + j];
rowlen += predecessors;
int cell = topleft + i*cw + j*ch*lw;
int center = cell + cw/2 + (ch/2)*lw;
int dx, dy;
- board[cell] = 0 ? center : '+';
+ board[cell] = false ? center : '+';
for (dx = 1; dx < cw; ++dx) board[cell + dx] = '-';
for (dy = 1; dy < ch; ++dy) board[cell + dy*lw] = '|';
if (state->grid[i*w+j] == GRID_UNKNOWN) continue;
}
struct game_ui {
- int dragging;
+ bool dragging;
int drag_start_x;
int drag_start_y;
int drag_end_x;
int drag_end_y;
int drag, release, state;
- int cur_x, cur_y, cur_visible;
+ int cur_x, cur_y;
+ bool cur_visible;
};
static game_ui *new_ui(const game_state *state)
ret = snew(game_ui);
ret->dragging = false;
- ret->cur_x = ret->cur_y = ret->cur_visible = 0;
+ ret->cur_x = ret->cur_y = 0;
+ ret->cur_visible = false;
return ret;
}
}
struct game_drawstate {
- int started;
+ bool started;
int w, h;
int tilesize;
unsigned char *visible, *numcolours;
const game_drawstate *ds,
int x, int y, int button)
{
- int control = button & MOD_CTRL, shift = button & MOD_SHFT;
+ bool control = button & MOD_CTRL, shift = button & MOD_SHFT;
button &= ~MOD_MASK;
x = FROMCOORD(state->common->w, x);
ui->drag_start_x = ui->drag_end_x = x;
ui->drag_start_y = ui->drag_end_y = y;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
return UI_UPDATE;
}
if (ui->dragging && button == ui->release) {
int x1, x2, y1, y2, xx, yy;
- int move_needed = false;
+ bool move_needed = false;
x1 = min(ui->drag_start_x, ui->drag_end_x);
x2 = max(ui->drag_start_x, ui->drag_end_x);
if (IS_CURSOR_MOVE(button)) {
int x = ui->cur_x, y = ui->cur_y, newstate;
char buf[80];
- move_cursor(button, &ui->cur_x, &ui->cur_y, state->common->w, state->common->h, 0);
- ui->cur_visible = 1;
+ move_cursor(button, &ui->cur_x, &ui->cur_y, state->common->w, state->common->h, false);
+ ui->cur_visible = true;
if (!control && !shift) return UI_UPDATE;
newstate = control ? shift ? GRID_UNKNOWN : GRID_FULL : GRID_EMPTY;
char buf[80];
if (!ui->cur_visible) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
int ncontig;
};
-static int errcheck_found_run(struct errcheck_state *es, int r)
+static bool errcheck_found_run(struct errcheck_state *es, int r)
{
/* Macro to handle the pretence that rowdata has a 0 at each end */
#define ROWDATA(k) ((k)<0 || (k)>=es->rowlen ? 0 : es->rowdata[(k)])
#undef ROWDATA
}
-static int check_errors(const game_state *state, int i)
+static bool check_errors(const game_state *state, int i)
{
int start, step, end, j;
int val, runlen;
}
static void grid_square(drawing *dr, game_drawstate *ds,
- int y, int x, int state, int cur)
+ int y, int x, int state, bool cur)
{
int xl, xr, yt, yb, dx, dy, dw, dh;
/*
* Draw the numbers for a single row or column.
*/
-static void draw_numbers(drawing *dr, game_drawstate *ds,
- const game_state *state, int i, int erase, int colour)
+static void draw_numbers(
+ drawing *dr, game_drawstate *ds, const game_state *state,
+ int i, bool erase, int colour)
{
int rowlen = state->common->rowlen[i];
int *rowdata = state->common->rowdata + state->common->rowsize * i;
{
int i, j;
int x1, x2, y1, y2;
- int cx, cy, cmoved;
+ int cx, cy;
+ bool cmoved;
if (!ds->started) {
/*
*/
for (i = 0; i < ds->h; i++) {
for (j = 0; j < ds->w; j++) {
- int val, cc = 0;
+ int val;
+ bool cc = false;
/*
* Work out what state this square should be drawn in,
if (cmoved) {
/* the cursor has moved; if we were the old or
* the new cursor position we need to redraw. */
- if (j == cx && i == cy) cc = 1;
- if (j == ds->cur_x && i == ds->cur_y) cc = 1;
+ if (j == cx && i == cy) cc = true;
+ if (j == ds->cur_x && i == ds->cur_y) cc = true;
}
/*
struct game_params {
int w, h;
int difficulty;
- int nosolve; /* XXX remove me! */
+ bool nosolve; /* XXX remove me! */
};
struct shared_state {
char *lines; /* size w*h: lines placed */
char *errors; /* size w*h: errors detected */
char *marks; /* size w*h: 'no line here' marks placed. */
- int completed, used_solve;
+ bool completed, used_solve;
};
#define DEFAULT_PRESET 3
*/
int pearl_solve(int w, int h, char *clues, char *result,
- int difficulty, int partial)
+ int difficulty, bool partial)
{
int W = 2*w+1, H = 2*h+1;
short *workspace;
* Now repeatedly try to find something we can do.
*/
while (1) {
- int done_something = false;
+ bool done_something = false;
#ifdef SOLVER_DIAGNOSTICS
for (y = 0; y < H; y++) {
struct pearl_loopgen_bias_ctx_boundary {
int colour; /* FACE_WHITE or FACE_BLACK */
- char *edges; /* is each edge part of the loop? */
+ bool *edges; /* is each edge part of the loop? */
tdq *edges_todo;
char *vertextypes; /* bits 0-3 == outgoing edge bitmap;
grid_edge *e = &g->edges[j];
int fc1 = e->face1 ? board[e->face1 - g->faces] : FACE_BLACK;
int fc2 = e->face2 ? board[e->face2 - g->faces] : FACE_BLACK;
- int oldedge = b->edges[j];
- int newedge = (fc1==c) ^ (fc2==c);
+ bool oldedge = b->edges[j];
+ bool newedge = (fc1==c) ^ (fc2==c);
if (oldedge != newedge) {
b->edges[j] = newedge;
tdq_add(b->vertextypes_todo, e->dot1 - g->dots);
biasctx.score = 0;
memset(biasctx.faces, FACE_GREY, g->num_faces);
for (i = 0; i < 2; i++) {
- biasctx.boundaries[i].edges = snewn(g->num_edges, char);
- memset(biasctx.boundaries[i].edges, 0, g->num_edges);
+ biasctx.boundaries[i].edges = snewn(g->num_edges, bool);
+ memset(biasctx.boundaries[i].edges, 0, g->num_edges * sizeof(bool));
biasctx.boundaries[i].edges_todo = tdq_new(g->num_edges);
tdq_fill(biasctx.boundaries[i].edges_todo);
biasctx.boundaries[i].vertextypes = snewn(g->num_dots, char);
game_state *state = snew(game_state);
int i, j, sz = params->w*params->h;
- state->completed = state->used_solve = false;
+ state->completed = false;
+ state->used_solve = false;
state->shared = snew(struct shared_state);
state->shared->w = params->w;
dsf_merge(dsf, ac, bc);
}
-static void check_completion(game_state *state, int mark)
+static void check_completion(game_state *state, bool mark)
{
int w = state->shared->w, h = state->shared->h, x, y, i, d;
- int had_error = false;
+ bool had_error = false;
int *dsf, *component_state;
int nsilly, nloop, npath, largest_comp, largest_size, total_pathsize;
enum { COMP_NONE, COMP_LOOP, COMP_PATH, COMP_SILLY, COMP_EMPTY };
int clickx, clicky; /* pixel position of initial click */
int curx, cury; /* grid position of keyboard cursor */
- int cursor_active; /* true iff cursor is shown */
+ bool cursor_active; /* true iff cursor is shown */
};
static game_ui *new_ui(const game_state *state)
struct game_drawstate {
int halfsz;
- int started;
+ bool started;
int w, h, sz;
unsigned int *lflags; /* size w*h */
*
* Call it in a loop, like this:
*
- * int clearing = true;
+ * bool clearing = true;
* for (i = 0; i < ui->ndragcoords - 1; i++) {
* int sx, sy, dx, dy, dir, oldstate, newstate;
* interpret_ui_drag(state, ui, &clearing, i, &sx, &sy, &dx, &dy,
* }
*/
static void interpret_ui_drag(const game_state *state, const game_ui *ui,
- int *clearing, int i, int *sx, int *sy,
+ bool *clearing, int i, int *sx, int *sy,
int *dx, int *dy, int *dir,
int *oldstate, int *newstate)
{
}
static char *mark_in_direction(const game_state *state, int x, int y, int dir,
- int primary, char *buf)
+ bool primary, char *buf)
{
int w = state->shared->w /*, h = state->shared->h, sz = state->shared->sz */;
int x2 = x + DX(dir);
{
int w = state->shared->w, h = state->shared->h /*, sz = state->shared->sz */;
int gx = FROMCOORD(x), gy = FROMCOORD(y), i;
- int release = false;
+ bool release = false;
char tmpbuf[80];
- int shift = button & MOD_SHFT, control = button & MOD_CTRL;
+ bool shift = button & MOD_SHFT, control = button & MOD_CTRL;
button &= ~MOD_MASK;
if (IS_MOUSE_DOWN(button)) {
if (IS_CURSOR_MOVE(button)) {
if (!ui->cursor_active) {
ui->cursor_active = true;
- } else if (control | shift) {
+ } else if (control || shift) {
char *move;
if (ui->ndragcoords > 0) return NULL;
ui->ndragcoords = -1;
int buflen = 0, bufsize = 256, tmplen;
char *buf = NULL;
const char *sep = "";
- int clearing = true;
+ bool clearing = true;
for (i = 0; i < ui->ndragcoords - 1; i++) {
int sx, sy, dx, dy, dir, oldstate, newstate;
float animtime, float flashtime)
{
int w = state->shared->w, h = state->shared->h, sz = state->shared->sz;
- int x, y, force = 0, flashing = 0;
+ int x, y, flashing = 0;
+ bool force = false;
if (!ds->started) {
/*
draw_update(dr, 0, 0, w*TILE_SIZE + 2*BORDER, h*TILE_SIZE + 2*BORDER);
ds->started = true;
- force = 1;
+ force = true;
}
if (flashtime > 0 &&
memset(ds->draglines, 0, sz);
if (ui->ndragcoords > 0) {
- int i, clearing = true;
+ int i;
+ bool clearing = true;
for (i = 0; i < ui->ndragcoords - 1; i++) {
int sx, sy, dx, dy, dir, oldstate, newstate;
interpret_ui_drag(state, ui, &clearing, i, &sx, &sy, &dx, &dy,
}
decode_params(p, id);
- err = validate_params(p, 1);
+ err = validate_params(p, true);
if (err) {
fprintf(stderr, "%s: %s", argv[0], err);
goto done;
struct game_state {
int w, h;
- int completed;
+ bool completed;
unsigned char *grid;
};
state->w = w;
state->h = h;
- state->completed = 0;
+ state->completed = false;
state->grid = snewn(w*h, unsigned char);
for (i = 0; i < w*h; i++)
state->grid[i] = (desc[i] == 'P' ? GRID_PEG :
}
struct game_ui {
- int dragging; /* boolean: is a drag in progress? */
+ bool dragging; /* is a drag in progress? */
int sx, sy; /* grid coords of drag start cell */
int dx, dy; /* pixel coords of current drag posn */
- int cur_x, cur_y, cur_visible, cur_jumping;
+ int cur_x, cur_y;
+ bool cur_visible, cur_jumping;
};
static game_ui *new_ui(const game_state *state)
ui->sx = ui->sy = ui->dx = ui->dy = 0;
ui->dragging = false;
- ui->cur_visible = ui->cur_jumping = 0;
+ ui->cur_visible = false;
+ ui->cur_jumping = false;
/* make sure we start the cursor somewhere on the grid. */
for (x = 0; x < state->w; x++) {
struct game_drawstate {
int tilesize;
blitter *drag_background;
- int dragging, dragx, dragy;
+ bool dragging;
+ int dragx, dragy;
int w, h;
unsigned char *grid;
- int started;
+ bool started;
int bgcolour;
};
ui->sy = ty;
ui->dx = x;
ui->dy = y;
- ui->cur_visible = ui->cur_jumping = 0;
+ ui->cur_visible = false;
+ ui->cur_jumping = false;
return UI_UPDATE;
}
} else if (button == LEFT_DRAG && ui->dragging) {
/* Not jumping; move cursor as usual, making sure we don't
* leave the gameboard (which may be an irregular shape) */
int cx = ui->cur_x, cy = ui->cur_y;
- move_cursor(button, &cx, &cy, w, h, 0);
- ui->cur_visible = 1;
+ move_cursor(button, &cx, &cy, w, h, false);
+ ui->cur_visible = true;
if (state->grid[cy*w+cx] == GRID_HOLE ||
state->grid[cy*w+cx] == GRID_PEG) {
ui->cur_x = cx;
mx = ui->cur_x+dx; my = ui->cur_y+dy;
jx = mx+dx; jy = my+dy;
- ui->cur_jumping = 0; /* reset, whatever. */
+ ui->cur_jumping = false; /* reset, whatever. */
if (jx >= 0 && jy >= 0 && jx < w && jy < h &&
state->grid[my*w+mx] == GRID_PEG &&
state->grid[jy*w+jx] == GRID_HOLE) {
}
} else if (IS_CURSOR_SELECT(button)) {
if (!ui->cur_visible) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
if (ui->cur_jumping) {
- ui->cur_jumping = 0;
+ ui->cur_jumping = false;
return UI_UPDATE;
}
if (state->grid[ui->cur_y*w+ui->cur_x] == GRID_PEG) {
/* cursor is on peg: next arrow-move wil jump. */
- ui->cur_jumping = 1;
+ ui->cur_jumping = true;
return UI_UPDATE;
}
return NULL;
if (ret->grid[i] == GRID_PEG)
count++;
if (count == 1)
- ret->completed = 1;
+ ret->completed = true;
}
return ret;
static void draw_tile(drawing *dr, game_drawstate *ds,
int x, int y, int v, int bgcolour)
{
- int cursor = 0, jumping = 0, bg;
+ bool cursor = false, jumping = false;
+ int bg;
if (bgcolour >= 0) {
draw_rect(dr, x, y, TILESIZE, TILESIZE, bgcolour);
}
if (v >= GRID_JUMPING) {
- jumping = 1; v -= GRID_JUMPING;
+ jumping = true; v -= GRID_JUMPING;
}
if (v >= GRID_CURSOR) {
- cursor = 1; v -= GRID_CURSOR;
+ cursor = true; v -= GRID_CURSOR;
}
if (v == GRID_HOLE) {
int npuzzles;
struct puzzle *puzzles;
int puzzlesize;
- int got_solns;
+ bool got_solns;
float *colwid, *rowht;
float userscale;
};
struct psdata {
FILE *fp;
- int colour;
+ bool colour;
int ytop;
- int clipped;
+ bool clipped;
float hatchthick, hatchspace;
int gamewidth, gameheight;
drawing *drawing;
struct game_state {
struct game_params params;
- unsigned int has_cheated: 1;
- unsigned int was_solved: 1;
+ bool has_cheated, was_solved;
puzzle_size *grid;
};
state.params = *params;
state.grid = grid;
- interactive = 0; /* I don't need it, I shouldn't use it*/
+ interactive = false; /* I don't need it, I shouldn't use it*/
for (i = 0; i < n; ++i) shuffle_1toN[i] = i;
struct game_ui {
puzzle_size r, c; /* cursor position */
- unsigned int cursor_show: 1;
+ bool cursor_show;
};
static game_ui *new_ui(const game_state *state)
typedef struct drawcell {
puzzle_size value;
- unsigned int error: 1;
- unsigned int cursor: 1;
- unsigned int flash: 1;
+ bool error, cursor, flash;
} drawcell;
struct game_drawstate {
int tilesize;
drawcell *grid;
- unsigned int started: 1;
+ bool started;
};
#define TILESIZE (ds->tilesize)
enum {none, forwards, backwards, hint};
int const w = state->params.w, h = state->params.h;
int r = ui->r, c = ui->c, action = none, cell;
- int shift = button & MOD_SHFT;
- button &= ~shift;
+ bool shift = button & MOD_SHFT;
+ button &= ~MOD_SHFT;
if (IS_CURSOR_SELECT(button) && !ui->cursor_show) return NULL;
for (i = 0; i < 4 && cursors[i] != button; ++i);
assert (i < 4);
if (shift) {
- int pre_r = r, pre_c = c, do_pre, do_post;
+ int pre_r = r, pre_c = c;
+ bool do_pre, do_post;
cell = state->grid[idx(r, c, state->params.w)];
do_pre = (cell == EMPTY);
return NULL;
}
-static int find_errors(const game_state *state, int *report)
+static bool find_errors(const game_state *state, bool *report)
{
int const w = state->params.w, h = state->params.h, n = w * h;
int *dsf;
ret->grid[idx(r, c, ret->params.w)] = value;
}
- if (ret->was_solved == false)
+ if (!ret->was_solved)
ret->was_solved = !find_errors(ret, NULL);
return ret;
return ret;
}
-static drawcell makecell(puzzle_size value, int error, int cursor, int flash)
+static drawcell makecell(puzzle_size value,
+ bool error, bool cursor, bool flash)
{
drawcell ret;
setmember(ret, value);
#define cmpmember(a, b, field) ((a) . field == (b) . field)
-static int cell_eq(drawcell a, drawcell b)
+static bool cell_eq(drawcell a, drawcell b)
{
return
cmpmember(a, b, value) &&
int r, c, i;
- int *errors = snewn(n, int);
- memset(errors, false, n * sizeof (int));
+ bool *errors = snewn(n, bool);
+ memset(errors, 0, n * sizeof (bool));
find_errors(state, errors);
assert (oldstate == NULL); /* only happens if animating moves */
struct game_params {
int w, h;
float expandfactor;
- int unique;
+ bool unique;
};
#define INDEX(state, x, y) (((y) * (state)->w) + (x))
int *grid; /* contains the numbers */
unsigned char *vedge; /* (w+1) x h */
unsigned char *hedge; /* w x (h+1) */
- int completed, cheated;
+ bool completed, cheated;
unsigned char *correct;
};
* Now run the actual deduction loop.
*/
while (1) {
- int done_something = false;
+ bool done_something = false;
#ifdef SOLVER_DIAGNOSTICS
printf("starting deduction loop\n");
for (j = 0; j < rectpositions[i].n; j++) {
int xx, yy, k;
- int del = false;
+ bool del = false;
for (k = 0; k < nrects; k++)
workspace[k] = 0;
if (index(state,ret,x,y) == 0xFF) {
int rw, rh;
int xx, yy;
- int num, area, valid;
+ int num, area;
+ bool valid;
/*
* Find a rectangle starting at this point.
state->grid = snewn(area, int);
state->vedge = snewn(area, unsigned char);
state->hedge = snewn(area, unsigned char);
- state->completed = state->cheated = false;
+ state->completed = false;
+ state->cheated = false;
i = 0;
while (*desc) {
* the pointer _returns_ to its starting point the action is
* treated as a small drag rather than a click.
*/
- int dragged;
+ bool dragged;
/* This flag is set if we're doing an erase operation (i.e.
* removing edges in the centre of the rectangle without altering
* the outlines).
*/
- int erasing;
+ bool erasing;
/*
* These are the co-ordinates of the top-left and bottom-right squares
* in the drag box, respectively, or -1 otherwise.
* These are the coordinates of a cursor, whether it's visible, and
* whether it was used to start a drag.
*/
- int cur_x, cur_y, cur_visible, cur_dragging;
+ int cur_x, cur_y;
+ bool cur_visible, cur_dragging;
};
static void reset_ui(game_ui *ui)
game_ui *ui = snew(game_ui);
reset_ui(ui);
ui->erasing = false;
- ui->cur_x = ui->cur_y = ui->cur_visible = ui->cur_dragging = 0;
+ ui->cur_x = ui->cur_y = 0;
+ ui->cur_visible = false;
+ ui->cur_dragging = false;
return ui;
}
/*
* Returns true if it has made any change to the grid.
*/
-static int grid_draw_rect(const game_state *state,
+static bool grid_draw_rect(const game_state *state,
unsigned char *hedge, unsigned char *vedge,
- int c, int really, int outline,
+ int c, bool really, bool outline,
int x1, int y1, int x2, int y2)
{
int x, y;
- int changed = false;
+ bool changed = false;
/*
* Draw horizontal edges of rectangles.
return changed;
}
-static int ui_draw_rect(const game_state *state, const game_ui *ui,
+static bool ui_draw_rect(const game_state *state, const game_ui *ui,
unsigned char *hedge, unsigned char *vedge, int c,
- int really, int outline)
+ bool really, bool outline)
{
return grid_draw_rect(state, hedge, vedge, c, really, outline,
ui->x1, ui->y1, ui->x2, ui->y2);
}
struct game_drawstate {
- int started;
+ bool started;
int w, h, tilesize;
unsigned long *visible;
};
int x, int y, int button)
{
int xc, yc;
- int startdrag = false, enddrag = false, active = false, erasing = false;
+ bool startdrag = false, enddrag = false, active = false, erasing = false;
char buf[80], *ret;
button &= ~MOD_MASK;
enddrag = true;
erasing = (button == RIGHT_RELEASE);
} else if (IS_CURSOR_MOVE(button)) {
- move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, 0);
+ move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, false);
ui->cur_visible = true;
active = true;
if (!ui->cur_dragging) return UI_UPDATE;
* if the game has been completed.
*/
if (!ret->completed) {
- int x, y, ok;
+ int x, y;
+ bool ok;
ok = true;
for (x = 0; x < ret->w; x++)
/* scoresub is 1 or 2 (for (n-1)^2 or (n-2)^2) */
struct game_params {
int w, h, ncols, scoresub;
- int soluble; /* choose generation algorithm */
+ bool soluble; /* choose generation algorithm */
};
/* These flags must be unique across all uses; in the game_state,
int n;
int *tiles; /* colour only */
int score;
- int complete, impossible;
+ bool complete, impossible;
};
static game_params *default_params(void)
int wh = w*h, tc = nc+1;
int i, j, k, c, x, y, pos, n;
int *list, *grid2;
- int ok, failures = 0;
+ bool ok;
+ int failures = 0;
/*
* We'll use `list' to track the possible places to put our
*/
{
int x1, x2, y1, y2;
- int ok = true;
+ bool ok = true;
int fillstart = -1, ntc = 0;
#ifdef GENERATION_DIAGNOSTICS
#endif
for (x1 = x2 = 0; x2 < w; x2++) {
- int usedcol = false;
+ bool usedcol = false;
for (y1 = y2 = h-1; y2 >= 0; y2--) {
if (grid2[y2*w+x2] == tc) {
p++;
if (*p) p++; /* eat comma */
}
- state->complete = state->impossible = 0;
+ state->complete = false;
+ state->impossible = false;
state->score = 0;
return state;
struct game_params params;
int *tiles; /* selected-ness only */
int nselected;
- int xsel, ysel, displaysel;
+ int xsel, ysel;
+ bool displaysel;
};
static game_ui *new_ui(const game_state *state)
memset(ui->tiles, 0, state->n*sizeof(int));
ui->nselected = 0;
- ui->xsel = ui->ysel = ui->displaysel = 0;
+ ui->xsel = ui->ysel = 0;
+ ui->displaysel = false;
return ui;
}
* control cursor.
*/
if (newstate->complete || newstate->impossible)
- ui->displaysel = 0;
+ ui->displaysel = false;
}
static char *sel_movedesc(game_ui *ui, const game_state *state)
}
}
-static int sg_emptycol(game_state *ret, int x)
+static bool sg_emptycol(game_state *ret, int x)
{
int y;
for (y = 0; y < ret->params.h; y++) {
- if (COL(ret,x,y)) return 0;
+ if (COL(ret,x,y)) return false;
}
- return 1;
+ return true;
}
static void sg_check(game_state *ret)
{
- int x,y, complete = 1, impossible = 1;
+ int x,y;
+ bool complete = true, impossible = true;
for (x = 0; x < ret->params.w; x++) {
for (y = 0; y < ret->params.h; y++) {
if (COL(ret,x,y) == 0)
continue;
- complete = 0;
+ complete = false;
if (x+1 < ret->params.w) {
if (COL(ret,x,y) == COL(ret,x+1,y))
- impossible = 0;
+ impossible = false;
}
if (y+1 < ret->params.h) {
if (COL(ret,x,y) == COL(ret,x,y+1))
- impossible = 0;
+ impossible = false;
}
}
}
}
struct game_drawstate {
- int started, bgcolour;
+ bool started;
+ int bgcolour;
int tileinner, tilegap;
int *tiles; /* contains colour and SELECTED. */
};
int tx, ty;
char *ret = UI_UPDATE;
- ui->displaysel = 0;
+ ui->displaysel = false;
if (button == RIGHT_BUTTON || button == LEFT_BUTTON) {
tx = FROMCOORD(x); ty= FROMCOORD(y);
} else if (IS_CURSOR_MOVE(button)) {
int dx = 0, dy = 0;
- ui->displaysel = 1;
+ ui->displaysel = true;
dx = (button == CURSOR_LEFT) ? -1 : ((button == CURSOR_RIGHT) ? +1 : 0);
dy = (button == CURSOR_DOWN) ? +1 : ((button == CURSOR_UP) ? -1 : 0);
ui->xsel = (ui->xsel + state->params.w + dx) % state->params.w;
ui->ysel = (ui->ysel + state->params.h + dy) % state->params.h;
return ret;
} else if (IS_CURSOR_SELECT(button)) {
- ui->displaysel = 1;
+ ui->displaysel = true;
tx = ui->xsel;
ty = ui->ysel;
} else
struct game_drawstate *ds = snew(struct game_drawstate);
int i;
- ds->started = 0;
+ ds->started = false;
ds->tileinner = ds->tilegap = 0; /* not decided yet */
ds->tiles = snewn(state->n, int);
ds->bgcolour = -1;
*/
static void tile_redraw(drawing *dr, game_drawstate *ds,
- int x, int y, int dright, int dbelow,
+ int x, int y, bool dright, bool dbelow,
int tile, int bgcolour)
{
int outer = bgcolour, inner = outer, col = tile & TILE_COLMASK;
coords[0] = COORD(0) - HIGHLIGHT_WIDTH;
draw_polygon(dr, coords, 5, COL_LOWLIGHT, COL_LOWLIGHT);
- ds->started = 1;
+ ds->started = true;
}
if (flashtime > 0.0) {
for (y = 0; y < state->params.h; y++) {
int i = (state->params.w * y) + x;
int col = COL(state,x,y), tile = col;
- int dright = (x+1 < state->params.w);
- int dbelow = (y+1 < state->params.h);
+ bool dright = (x+1 < state->params.w);
+ bool dbelow = (y+1 < state->params.h);
tile |= ISSEL(ui,x,y);
if (state->impossible)
struct game_params {
int w, h;
- int force_corner_start;
+ bool force_corner_start;
};
enum { DIR_N = 0, DIR_NE, DIR_E, DIR_SE, DIR_S, DIR_SW, DIR_W, DIR_NW, DIR_MAX };
struct game_state {
int w, h, n;
- int completed, used_solve, impossible;
+ bool completed, used_solve, impossible;
int *dirs; /* direction enums, size n */
int *nums; /* numbers, size n */
unsigned int *flags; /* flags, size n */
return whichdir(fromi%w, fromi/w, toi%w, toi/w);
}
-static int ispointing(const game_state *state, int fromx, int fromy,
- int tox, int toy)
+static bool ispointing(const game_state *state, int fromx, int fromy,
+ int tox, int toy)
{
int w = state->w, dir = state->dirs[fromy*w+fromx];
/* (by convention) squares do not point to themselves. */
- if (fromx == tox && fromy == toy) return 0;
+ if (fromx == tox && fromy == toy) return false;
/* the final number points to nothing. */
- if (state->nums[fromy*w + fromx] == state->n) return 0;
+ if (state->nums[fromy*w + fromx] == state->n) return false;
while (1) {
- if (!INGRID(state, fromx, fromy)) return 0;
- if (fromx == tox && fromy == toy) return 1;
+ if (!INGRID(state, fromx, fromy)) return false;
+ if (fromx == tox && fromy == toy) return true;
fromx += dxs[dir]; fromy += dys[dir];
}
- return 0; /* not reached */
+ return false; /* not reached */
}
-static int ispointingi(game_state *state, int fromi, int toi)
+static bool ispointingi(game_state *state, int fromi, int toi)
{
int w = state->w;
return ispointing(state, fromi%w, fromi/w, toi%w, toi/w);
}
/* Taking the number 'num', work out the gap between it and the next
- * available number up or down (depending on d). Return 1 if the region
- * at (x,y) will fit in that gap, or 0 otherwise. */
-static int move_couldfit(const game_state *state, int num, int d, int x, int y)
+ * available number up or down (depending on d). Return true if the
+ * region at (x,y) will fit in that gap. */
+static bool move_couldfit(
+ const game_state *state, int num, int d, int x, int y)
{
int n, gap, i = y*state->w+x, sz;
/* no gap, so the only allowable move is that that directly
* links the two numbers. */
n = state->nums[i];
- return (n == num+d) ? 0 : 1;
+ return n != num+d;
}
if (state->prev[i] == -1 && state->next[i] == -1)
- return 1; /* single unconnected square, always OK */
+ return true; /* single unconnected square, always OK */
sz = dsf_size(state->dsf, i);
- return (sz > gap) ? 0 : 1;
+ return sz <= gap;
}
-static int isvalidmove(const game_state *state, int clever,
- int fromx, int fromy, int tox, int toy)
+static bool isvalidmove(const game_state *state, bool clever,
+ int fromx, int fromy, int tox, int toy)
{
int w = state->w, from = fromy*w+fromx, to = toy*w+tox;
int nfrom, nto;
if (!INGRID(state, fromx, fromy) || !INGRID(state, tox, toy))
- return 0;
+ return false;
/* can only move where we point */
if (!ispointing(state, fromx, fromy, tox, toy))
- return 0;
+ return false;
nfrom = state->nums[from]; nto = state->nums[to];
/* can't move _from_ the preset final number, or _to_ the preset 1. */
if (((nfrom == state->n) && (state->flags[from] & FLAG_IMMUTABLE)) ||
((nto == 1) && (state->flags[to] & FLAG_IMMUTABLE)))
- return 0;
+ return false;
/* can't create a new connection between cells in the same region
* as that would create a loop. */
if (dsf_canonify(state->dsf, from) == dsf_canonify(state->dsf, to))
- return 0;
+ return false;
/* if both cells are actual numbers, can't drag if we're not
* one digit apart. */
if (ISREALNUM(state, nfrom) && ISREALNUM(state, nto)) {
if (nfrom != nto-1)
- return 0;
+ return false;
} else if (clever && ISREALNUM(state, nfrom)) {
if (!move_couldfit(state, nfrom, +1, tox, toy))
- return 0;
+ return false;
} else if (clever && ISREALNUM(state, nto)) {
if (!move_couldfit(state, nto, -1, fromx, fromy))
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static void makelink(game_state *state, int from, int to)
static bool game_can_format_as_text_now(const game_params *params)
{
- if (params->w * params->h >= 100) return 0;
- return 1;
+ if (params->w * params->h >= 100) return false;
+ return true;
}
static char *game_text_format(const game_state *state)
dsf_init(state->dsf, state->n);
}
-static int check_nums(game_state *orig, game_state *copy, int only_immutable)
+static bool check_nums(game_state *orig, game_state *copy, bool only_immutable)
{
- int i, ret = 1;
+ int i;
+ bool ret = true;
assert(copy->n == orig->n);
for (i = 0; i < copy->n; i++) {
if (only_immutable && !(copy->flags[i] & FLAG_IMMUTABLE)) continue;
if (copy->nums[i] != orig->nums[i]) {
debug(("check_nums: (%d,%d) copy=%d, orig=%d.",
i%orig->w, i/orig->w, copy->nums[i], orig->nums[i]));
- ret = 0;
+ ret = false;
}
}
return ret;
{
game_params *ret = snew(game_params);
ret->w = ret->h = 4;
- ret->force_corner_start = 1;
+ ret->force_corner_start = true;
return ret;
}
ret->h = atoi(string);
while (*string && isdigit((unsigned char)*string)) string++;
}
- ret->force_corner_start = 0;
+ ret->force_corner_start = false;
if (*string == 'c') {
string++;
- ret->force_corner_start = 1;
+ ret->force_corner_start = true;
}
}
}
}
-static char *generate_desc(game_state *state, int issolve)
+static char *generate_desc(game_state *state, bool issolve)
{
char *ret, buf[80];
int retlen, i, k;
return n;
}
-static int new_game_fill(game_state *state, random_state *rs,
- int headi, int taili)
+static bool new_game_fill(game_state *state, random_state *rs,
+ int headi, int taili)
{
- int nfilled, an, ret = 0, j;
+ int nfilled, an, j;
+ bool ret = false;
int *aidx, *adir;
aidx = snewn(state->n, int);
/* it could happen that our last two weren't in line; if that's the
* case, we have to start again. */
- if (state->dirs[headi] != -1) ret = 1;
+ if (state->dirs[headi] != -1) ret = true;
done:
sfree(aidx);
/* Expects a fully-numbered game_state on input, and makes sure
* FLAG_IMMUTABLE is only set on those numbers we need to solve
- * (as for a real new-game); returns 1 if it managed
- * this (such that it could solve it), or 0 if not. */
-static int new_game_strip(game_state *state, random_state *rs)
+ * (as for a real new-game); returns true if it managed
+ * this (such that it could solve it), or false if not. */
+static bool new_game_strip(game_state *state, random_state *rs)
{
- int *scratch, i, j, ret = 1;
+ int *scratch, i, j;
+ bool ret = true;
game_state *copy = dup_game(state);
debug(("new_game_strip."));
if (solve_state(copy) > 0) {
debug(("new_game_strip: soluble immediately after strip."));
free_game(copy);
- return 1;
+ return true;
}
scratch = snewn(state->n, int);
debug_state("Copy of state: ", copy);
strip_nums(copy);
if (solve_state(copy) > 0) goto solved;
- assert(check_nums(state, copy, 1));
+ assert(check_nums(state, copy, true));
}
- ret = 0;
+ ret = false;
goto done;
solved:
dup_game_to(copy, state);
strip_nums(copy);
if (solve_state(copy) > 0) {
- assert(check_nums(state, copy, 0));
+ assert(check_nums(state, copy, false));
debug(("new_game_strip: OK, removing number"));
} else {
assert(state->nums[j] <= state->n);
assert(solve_state(tosolve) > 0);
free_game(tosolve);
}
- ret = generate_desc(state, 0);
+ ret = generate_desc(state, false);
free_game(state);
return ret;
}
head->why = "contains cell with immutable number";
} else if (head->start != ss) {
debug(("head_number: chain with non-sequential numbers!"));
- state->impossible = 1;
+ state->impossible = true;
}
}
off++;
dni = dsf_canonify(state->dsf, state->next[i]);
if (di == dni) {
debug(("connect_numbers: chain forms a loop."));
- state->impossible = 1;
+ state->impossible = true;
}
dsf_merge(state->dsf, di, dni);
}
sfree(heads);
}
-static int check_completion(game_state *state, int mark_errors)
+static bool check_completion(game_state *state, bool mark_errors)
{
- int n, j, k, error = 0, complete;
+ int n, j, k;
+ bool error = false, complete;
/* NB This only marks errors that are possible to perpetrate with
* the current UI in interpret_move. Things like forming loops in
state->flags[j] |= FLAG_ERROR;
state->flags[k] |= FLAG_ERROR;
}
- error = 1;
+ error = true;
}
}
}
/* Search and mark numbers n not pointing to n+1; if any numbers
* are missing we know we've not completed. */
- complete = 1;
+ complete = true;
for (n = 1; n < state->n; n++) {
if (state->numsi[n] == -1 || state->numsi[n+1] == -1)
- complete = 0;
+ complete = false;
else if (!ispointingi(state, state->numsi[n], state->numsi[n+1])) {
if (mark_errors) {
state->flags[state->numsi[n]] |= FLAG_ERROR;
state->flags[state->numsi[n+1]] |= FLAG_ERROR;
}
- error = 1;
+ error = true;
} else {
/* make sure the link is explicitly made here; for instance, this
* is nice if the user drags from 2 out (making 3) and a 4 is also
if ((state->nums[n] < 0) ||
(state->nums[n] == 0 &&
(state->next[n] != -1 || state->prev[n] != -1))) {
- error = 1;
+ error = true;
if (mark_errors)
state->flags[n] |= FLAG_ERROR;
}
}
- if (error) return 0;
+ if (error) return false;
return complete;
}
static game_state *new_game(midend *me, const game_params *params,
if (!state) assert(!"new_game failed to unpick");
update_numbers(state);
- check_completion(state, 1); /* update any auto-links */
+ check_completion(state, true); /* update any auto-links */
return state;
}
while (1) {
x += dxs[d]; y += dys[d];
if (!INGRID(state, x, y)) break;
- if (!isvalidmove(state, 1, sx, sy, x, y)) continue;
+ if (!isvalidmove(state, true, sx, sy, x, y)) continue;
/* can't link to somewhere with a back-link we would have to
* break (the solver just doesn't work like this). */
;
} else if (poss == -1) {
debug(("Solver: nowhere possible for (%d,%d) to link to.", sx, sy));
- copy->impossible = 1;
+ copy->impossible = true;
return -1;
} else {
debug(("Solver: linking (%d,%d) to only possible next (%d,%d).",
x = i%w; y = i/w;
if (from[i] == -1) {
debug(("Solver: nowhere possible to link to (%d,%d)", x, y));
- copy->impossible = 1;
+ copy->impossible = true;
return -1;
} else if (from[i] == -2) {
/*debug(("Solver: (%d,%d) has multiple possible prev squares.", x, y));*/
sfree(scratch);
update_numbers(state);
- ret = state->impossible ? -1 : check_completion(state, 0);
+ ret = state->impossible ? -1 : check_completion(state, false);
debug(("Solver finished: %s",
ret < 0 ? "impossible" : ret > 0 ? "solved" : "not solved"));
debug_state("After solver: ", state);
tosolve = dup_game(currstate);
result = solve_state(tosolve);
if (result > 0)
- ret = generate_desc(tosolve, 1);
+ ret = generate_desc(tosolve, true);
free_game(tosolve);
if (ret) return ret;
else if (result == 0)
*error = "Unable to solve puzzle.";
else
- ret = generate_desc(tosolve, 1);
+ ret = generate_desc(tosolve, true);
free_game(tosolve);
struct game_ui {
- int cx, cy, cshow;
+ int cx, cy;
+ bool cshow;
- int dragging, drag_is_from;
+ bool dragging, drag_is_from;
int sx, sy; /* grid coords of start cell */
int dx, dy; /* pixel coords of drag posn */
};
/* NB: if this is ever changed to as to require more than a structure
* copy to clone, there's code that needs fixing in game_redraw too. */
- ui->cx = ui->cy = ui->cshow = 0;
+ ui->cx = ui->cy = 0;
+ ui->cshow = false;
- ui->dragging = 0;
+ ui->dragging = false;
ui->sx = ui->sy = ui->dx = ui->dy = 0;
return ui;
static void game_changed_state(game_ui *ui, const game_state *oldstate,
const game_state *newstate)
{
- if (!oldstate->completed && newstate->completed)
- ui->cshow = ui->dragging = 0;
+ if (!oldstate->completed && newstate->completed) {
+ ui->cshow = false;
+ ui->dragging = false;
+ }
}
struct game_drawstate {
- int tilesize, started, solved;
+ int tilesize;
+ bool started, solved;
int w, h, n;
int *nums, *dirp;
unsigned int *f;
double angle_offset;
- int dragging, dx, dy;
+ bool dragging;
+ int dx, dy;
blitter *dragb;
};
char buf[80];
if (IS_CURSOR_MOVE(button)) {
- move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, 0);
- ui->cshow = 1;
+ move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, false);
+ ui->cshow = true;
if (ui->dragging) {
ui->dx = COORD(ui->cx) + TILE_SIZE/2;
ui->dy = COORD(ui->cy) + TILE_SIZE/2;
return UI_UPDATE;
} else if (IS_CURSOR_SELECT(button)) {
if (!ui->cshow)
- ui->cshow = 1;
+ ui->cshow = true;
else if (ui->dragging) {
ui->dragging = false;
if (ui->sx == ui->cx && ui->sy == ui->cy) return UI_UPDATE;
if (ui->drag_is_from) {
- if (!isvalidmove(state, 0, ui->sx, ui->sy, ui->cx, ui->cy))
+ if (!isvalidmove(state, false, ui->sx, ui->sy, ui->cx, ui->cy))
return UI_UPDATE;
sprintf(buf, "L%d,%d-%d,%d", ui->sx, ui->sy, ui->cx, ui->cy);
} else {
- if (!isvalidmove(state, 0, ui->cx, ui->cy, ui->sx, ui->sy))
+ if (!isvalidmove(state, false, ui->cx, ui->cy, ui->sx, ui->sy))
return UI_UPDATE;
sprintf(buf, "L%d,%d-%d,%d", ui->cx, ui->cy, ui->sx, ui->sy);
}
ui->sy = ui->cy;
ui->dx = COORD(ui->cx) + TILE_SIZE/2;
ui->dy = COORD(ui->cy) + TILE_SIZE/2;
- ui->drag_is_from = (button == CURSOR_SELECT) ? 1 : 0;
+ ui->drag_is_from = (button == CURSOR_SELECT);
}
return UI_UPDATE;
}
if (IS_MOUSE_DOWN(button)) {
if (ui->cshow) {
- ui->cshow = ui->dragging = 0;
+ ui->cshow = false;
+ ui->dragging = false;
}
assert(!ui->dragging);
if (!INGRID(state, x, y)) return NULL;
}
ui->dragging = true;
- ui->drag_is_from = (button == LEFT_BUTTON) ? 1 : 0;
+ ui->drag_is_from = (button == LEFT_BUTTON);
ui->sx = x;
ui->sy = y;
ui->dx = mx;
ui->dy = my;
- ui->cshow = 0;
+ ui->cshow = false;
return UI_UPDATE;
} else if (IS_MOUSE_DRAG(button) && ui->dragging) {
ui->dx = mx;
}
if (ui->drag_is_from) {
- if (!isvalidmove(state, 0, ui->sx, ui->sy, x, y))
+ if (!isvalidmove(state, false, ui->sx, ui->sy, x, y))
return UI_UPDATE;
sprintf(buf, "L%d,%d-%d,%d", ui->sx, ui->sy, x, y);
} else {
- if (!isvalidmove(state, 0, x, y, ui->sx, ui->sy))
+ if (!isvalidmove(state, false, x, y, ui->sx, ui->sy))
return UI_UPDATE;
sprintf(buf, "L%d,%d-%d,%d", x, y, ui->sx, ui->sy);
}
ret->next[i] = tmp->next[i];
}
free_game(tmp);
- ret->used_solve = 1;
+ ret->used_solve = true;
} else if (sscanf(move, "L%d,%d-%d,%d", &sx, &sy, &ex, &ey) == 4) {
- if (!isvalidmove(state, 0, sx, sy, ex, ey)) return NULL;
+ if (!isvalidmove(state, false, sx, sy, ex, ey)) return NULL;
ret = dup_game(state);
}
if (ret) {
update_numbers(ret);
- if (check_completion(ret, 1)) ret->completed = 1;
+ if (check_completion(ret, true)) ret->completed = true;
}
return ret;
struct game_drawstate *ds = snew(struct game_drawstate);
int i;
- ds->tilesize = ds->started = ds->solved = 0;
+ ds->tilesize = 0;
+ ds->started = false;
+ ds->solved = false;
ds->w = state->w;
ds->h = state->h;
ds->n = state->n;
ds->angle_offset = 0.0F;
- ds->dragging = ds->dx = ds->dy = 0;
+ ds->dragging = false;
+ ds->dx = ds->dy = 0;
ds->dragb = NULL;
return ds;
int cb = TILE_SIZE / 16, textsz;
char buf[20];
int arrowcol, sarrowcol, setcol, textcol;
- int acx, acy, asz, empty = 0;
+ int acx, acy, asz;
+ bool empty = false;
if (num == 0 && !(f & F_ARROW_POINT) && !(f & F_ARROW_INPOINT)) {
- empty = 1;
+ empty = true;
/*
* We don't display text in empty cells: typically these are
* signified by num=0. However, in some cases a cell could
static void draw_drag_indicator(drawing *dr, game_drawstate *ds,
const game_state *state, const game_ui *ui,
- int validdrag)
+ bool validdrag)
{
int dir, w = ds->w, acol = COL_ARROW;
int fx = FROMCOORD(ui->dx), fy = FROMCOORD(ui->dy);
int dir, const game_ui *ui,
float animtime, float flashtime)
{
- int x, y, i, w = ds->w, dirp, force = 0;
+ int x, y, i, w = ds->w, dirp;
+ bool force = false;
unsigned int f;
double angle_offset = 0.0;
game_state *postdrop = NULL;
angle_offset = 2.0 * PI * (flashtime / FLASH_SPIN);
if (angle_offset != ds->angle_offset) {
ds->angle_offset = angle_offset;
- force = 1;
+ force = true;
}
if (ds->dragging) {
ds->dy = ui->dy - BLITTER_SIZE/2;
blitter_save(dr, ds->dragb, ds->dx, ds->dy);
- draw_drag_indicator(dr, ds, state, ui, postdrop ? 1 : 0);
+ draw_drag_indicator(dr, ds, state, ui, postdrop != NULL);
}
if (postdrop) free_game(postdrop);
if (!ds->started) ds->started = true;
{
char *id = NULL, *desc, *aux = NULL;
const char *err;
- int soak = 0, verbose = 0, stdin_desc = 0, n = 1, i;
+ bool soak = false, verbose = false, stdin_desc = false;
+ int n = 1, i;
char *seedstr = NULL, newseed[16];
setvbuf(stdout, NULL, _IONBF, 0);
while (--argc > 0) {
char *p = (char*)(*++argv);
if (!strcmp(p, "-v") || !strcmp(p, "--verbose"))
- verbose = 1;
+ verbose = true;
else if (!strcmp(p, "--stdin"))
- stdin_desc = 1;
+ stdin_desc = true;
else if (!strcmp(p, "-e") || !strcmp(p, "--seed")) {
seedstr = dupstr(*++argv);
argc--;
n = atoi(*++argv);
argc--;
} else if (!strcmp(p, "-s") || !strcmp(p, "--soak")) {
- soak = 1;
+ soak = true;
} else if (*p == '-') {
fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0], p);
usage(stderr);
#include "latin.h"
#ifdef STANDALONE_SOLVER
-int verbose = 0;
+bool verbose = false;
#endif
#define PREFERRED_TILE_SIZE 32
struct game_state {
int w, h, n, o; /* n = w*h; o = max(w, h) */
- int completed, used_solve, impossible;
+ bool completed, used_solve, impossible;
int *nums; /* size w*h */
unsigned int *flags; /* size w*h */
};
state->n = w*h;
state->o = max(w,h);
- state->completed = state->used_solve = state->impossible = 0;
+ state->completed = false;
+ state->used_solve = false;
+ state->impossible = false;
state->nums = snewn(state->n, int);
state->flags = snewn(state->n, unsigned int);
}
}
-static char *generate_desc(game_state *state, int issolve)
+static char *generate_desc(game_state *state, bool issolve)
{
char *ret = snewn(state->n+1+(issolve?1:0), char);
int i, p=0;
return nerr;
}
-static int check_complete(game_state *state, unsigned flags)
+static bool check_complete(game_state *state, unsigned flags)
{
int *dsf = snewn(state->n, int);
int x, y, i, error = 0, nwhite, w = state->w, h = state->h;
}
sfree(dsf);
- return (error > 0) ? 0 : 1;
+ return !(error > 0);
}
static char *game_state_diff(const game_state *src, const game_state *dst,
- int issolve)
+ bool issolve)
{
char *ret = NULL, buf[80], c;
int retlen = 0, x, y, i, k;
if (!INGRID(state, x, y)) return;
if (state->flags[i] & F_BLACK) {
debug(("... solver wants to add auto-circle on black (%d,%d)\n", x, y));
- state->impossible = 1;
+ state->impossible = true;
return;
}
/* Only add circle op if it's not already circled. */
if (state->nums[i] != num) return;
if (state->flags[i] & F_CIRCLE) {
debug(("... solver wants to add auto-black on circled(%d,%d)\n", x, y));
- state->impossible = 1;
+ state->impossible = true;
return;
}
/* Only add black op if it's not already black. */
if (op.op == BLACK) {
if (state->flags[i] & F_CIRCLE) {
debug(("Solver wants to blacken circled square (%d,%d)!\n", op.x, op.y));
- state->impossible = 1;
+ state->impossible = true;
return n_ops;
}
if (!(state->flags[i] & F_BLACK)) {
} else {
if (state->flags[i] & F_BLACK) {
debug(("Solver wants to circle blackened square (%d,%d)!\n", op.x, op.y));
- state->impossible = 1;
+ state->impossible = true;
return n_ops;
}
if (!(state->flags[i] & F_CIRCLE)) {
"CC/CE/QM: white cell with single non-black around it");
else {
debug(("White cell with no escape at (%d,%d)\n", x, y));
- state->impossible = 1;
+ state->impossible = true;
return 0;
}
skip: ;
return ss->n_ops - n_ops;
}
-static int solve_hassinglewhiteregion(game_state *state, struct solver_state *ss)
+static bool solve_hassinglewhiteregion(
+ game_state *state, struct solver_state *ss)
{
int i, j, nwhite = 0, lwhite = -1, szwhite, start, end, next, a, d, x, y;
}
if (lwhite == -1) {
debug(("solve_hassinglewhite: no white squares found!\n"));
- state->impossible = 1;
- return 0;
+ state->impossible = true;
+ return false;
}
/* We don't use connect_dsf here; it's too slow, and there's a quicker
* algorithm if all we want is the size of one region. */
start = end; end = next;
}
szwhite = next;
- return (szwhite == nwhite) ? 1 : 0;
+ return (szwhite == nwhite);
}
static void solve_removesplits_check(game_state *state, struct solver_state *ss,
int x, int y)
{
- int i = y*state->w + x, issingle;
+ int i = y*state->w + x;
+ bool issingle;
if (!INGRID(state, x, y)) return;
if ((state->flags[i] & F_CIRCLE) || (state->flags[i] & F_BLACK))
if (!solve_hassinglewhiteregion(state, ss)) {
debug(("solve_removesplits: white region is not contiguous at start!\n"));
- state->impossible = 1;
+ state->impossible = true;
return 0;
}
return nunique;
}
-static int solve_specific(game_state *state, int diff, int sneaky)
+static int solve_specific(game_state *state, int diff, bool sneaky)
{
struct solver_state *ss = solver_state_new(state);
game_state *solved = dup_game(currstate);
char *move = NULL;
- if (solve_specific(solved, DIFF_ANY, 0) > 0) goto solved;
+ if (solve_specific(solved, DIFF_ANY, false) > 0) goto solved;
free_game(solved);
solved = dup_game(state);
- if (solve_specific(solved, DIFF_ANY, 0) > 0) goto solved;
+ if (solve_specific(solved, DIFF_ANY, false) > 0) goto solved;
free_game(solved);
*error = "Unable to solve puzzle.";
return NULL;
solved:
- move = game_state_diff(currstate, solved, 1);
+ move = game_state_diff(currstate, solved, true);
free_game(solved);
return move;
}
the solver gets a headstart working out where they are.
*/
-static int new_game_is_good(const game_params *params,
- game_state *state, game_state *tosolve)
+static bool new_game_is_good(const game_params *params,
+ game_state *state, game_state *tosolve)
{
int sret, sret_easy = 0;
memcpy(tosolve->nums, state->nums, state->n * sizeof(int));
memset(tosolve->flags, 0, state->n * sizeof(unsigned int));
- tosolve->completed = tosolve->impossible = 0;
+ tosolve->completed = false;
+ tosolve->impossible = false;
/*
* We try and solve it twice, once at our requested difficulty level
*/
assert(params->diff < DIFF_MAX);
- sret = solve_specific(tosolve, params->diff, 0);
+ sret = solve_specific(tosolve, params->diff, false);
if (params->diff > DIFF_EASY) {
memset(tosolve->flags, 0, state->n * sizeof(unsigned int));
- tosolve->completed = tosolve->impossible = 0;
+ tosolve->completed = false;
+ tosolve->impossible = false;
- /* this is the only time the 'sneaky' flag is set to 1. */
- sret_easy = solve_specific(tosolve, params->diff-1, 1);
+ /* this is the only time the 'sneaky' flag is set. */
+ sret_easy = solve_specific(tosolve, params->diff-1, true);
}
if (sret <= 0 || sret_easy > 0) {
debug(("Generated puzzle %s at chosen difficulty %s\n",
sret <= 0 ? "insoluble" : "too easy",
singles_diffnames[params->diff]));
- return 0;
+ return false;
}
- return 1;
+ return true;
}
#define MAXTRIES 20
goto randomise;
}
- ret = generate_desc(state, 0);
+ ret = generate_desc(state, false);
free_game(tosolve);
free_game(state);
/* --- Game UI and move routines --- */
struct game_ui {
- int cx, cy, cshow;
- int show_black_nums;
+ int cx, cy;
+ bool cshow, show_black_nums;
};
static game_ui *new_ui(const game_state *state)
{
game_ui *ui = snew(game_ui);
- ui->cx = ui->cy = ui->cshow = 0;
- ui->show_black_nums = 0;
+ ui->cx = ui->cy = 0;
+ ui->cshow = false;
+ ui->show_black_nums = false;
return ui;
}
const game_state *newstate)
{
if (!oldstate->completed && newstate->completed)
- ui->cshow = 0;
+ ui->cshow = false;
}
#define DS_BLACK 0x1
#define DS_IMPOSSIBLE 0x40
struct game_drawstate {
- int tilesize, started, solved;
+ int tilesize;
+ bool started, solved;
int w, h, n;
unsigned int *flags;
enum { NONE, TOGGLE_BLACK, TOGGLE_CIRCLE, UI } action = NONE;
if (IS_CURSOR_MOVE(button)) {
- move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, 1);
- ui->cshow = 1;
+ move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, true);
+ ui->cshow = true;
action = UI;
} else if (IS_CURSOR_SELECT(button)) {
x = ui->cx; y = ui->cy;
if (!ui->cshow) {
action = UI;
- ui->cshow = 1;
+ ui->cshow = true;
}
if (button == CURSOR_SELECT) {
action = TOGGLE_BLACK;
}
} else if (IS_MOUSE_DOWN(button)) {
if (ui->cshow) {
- ui->cshow = 0;
+ ui->cshow = false;
action = UI;
}
if (!INGRID(state, x, y)) {
- ui->show_black_nums = 1 - ui->show_black_nums;
+ ui->show_black_nums = !ui->show_black_nums;
action = UI; /* this wants to be a per-game option. */
} else if (button == LEFT_BUTTON) {
action = TOGGLE_BLACK;
move += n;
} else if (c == 'S') {
move++;
- ret->used_solve = 1;
+ ret->used_solve = true;
} else
goto badmove;
else if (*move)
goto badmove;
}
- if (check_complete(ret, CC_MARK_ERRORS)) ret->completed = 1;
+ if (check_complete(ret, CC_MARK_ERRORS)) ret->completed = true;
return ret;
badmove:
{
struct game_drawstate *ds = snew(struct game_drawstate);
- ds->tilesize = ds->started = ds->solved = 0;
+ ds->tilesize = 0;
+ ds->started = false;
+ ds->solved = false;
ds->w = state->w;
ds->h = state->h;
ds->n = state->n;
static void tile_redraw(drawing *dr, game_drawstate *ds, int x, int y,
int num, unsigned int f)
{
- int tcol, bg, dnum, cx, cy, tsz;
+ int tcol, bg, cx, cy, tsz;
+ bool dnum;
char buf[32];
if (f & DS_BLACK) {
bg = (f & DS_ERROR) ? COL_ERROR : COL_BLACK;
tcol = COL_BLACKNUM;
- dnum = (f & DS_BLACK_NUM) ? 1 : 0;
+ dnum = (f & DS_BLACK_NUM);
} else {
bg = (f & DS_FLASH) ? COL_LOWLIGHT : COL_BACKGROUND;
tcol = (f & DS_ERROR) ? COL_ERROR : COL_BLACK;
- dnum = 1;
+ dnum = true;
}
cx = x + TILE_SIZE/2; cy = y + TILE_SIZE/2;
}
}
}
- ds->started = 1;
+ ds->started = true;
}
static float game_anim_length(const game_state *oldstate,
while (1) {
n++;
- desc = new_game_desc(p, rs, &aux, 0);
+ desc = new_game_desc(p, rs, &aux, false);
s = new_game(NULL, p, desc);
nsneaky += solve_sneaky(s, NULL);
for (diff = 0; diff < DIFF_MAX; diff++) {
memset(s->flags, 0, s->n * sizeof(unsigned int));
- s->completed = s->impossible = 0;
- sret = solve_specific(s, diff, 0);
+ s->completed = false;
+ s->impossible = false;
+ sret = solve_specific(s, diff, false);
if (sret > 0) {
ndiff[diff]++;
break;
const char *err;
game_state *s = NULL;
game_params *p = NULL;
- int soln, soak = 0, ret = 1;
+ int soln, ret = 1;
+ bool soak = false;
time_t seed = time(NULL);
random_state *rs = NULL;
while (--argc > 0) {
char *p = *++argv;
if (!strcmp(p, "-v")) {
- verbose = 1;
+ verbose = true;
} else if (!strcmp(p, "--soak")) {
- soak = 1;
+ soak = true;
} else if (!strcmp(p, "--seed")) {
if (argc == 0) {
fprintf(stderr, "%s: --seed needs an argument", argv[0]);
p = default_params();
decode_params(p, id);
- err = validate_params(p, 1);
+ err = validate_params(p, true);
if (err) {
fprintf(stderr, "%s: %s", argv[0], err);
goto done;
}
start_soak(p, rs);
} else {
- if (!desc) desc = desc_gen = new_game_desc(p, rs, &aux, 0);
+ if (!desc) desc = desc_gen = new_game_desc(p, rs, &aux, false);
err = validate_desc(p, desc);
if (err) {
sfree(tgame);
}
- soln = solve_specific(s, DIFF_ANY, 0);
+ soln = solve_specific(s, DIFF_ANY, false);
tgame = game_text_format(s);
fputs(tgame, stdout);
sfree(tgame);
int w, h, n;
int *tiles;
int completed;
- int used_solve; /* used to suppress completion flash */
+ bool used_solve; /* used to suppress completion flash */
int movecount, movetarget;
int last_movement_sense;
};
{
int stop, n, i, x;
int x1, x2, p1, p2;
- int *tiles, *used;
+ int *tiles;
+ bool *used;
char *ret;
int retlen;
} else {
- used = snewn(n, int);
+ used = snewn(n, bool);
for (i = 0; i < n; i++) {
tiles[i] = -1;
{
const char *p, *err;
int i, area;
- int *used;
+ bool *used;
area = params->w * params->h;
p = desc;
err = NULL;
- used = snewn(area, int);
+ used = snewn(area, bool);
for (i = 0; i < area; i++)
used[i] = false;
struct game_ui {
int cur_x, cur_y;
- int cur_visible;
+ bool cur_visible;
enum cursor_mode cur_mode;
};
}
struct game_drawstate {
- int started;
+ bool started;
int w, h, bgcolour;
int *tiles;
int tilesize;
{
int cx = -1, cy = -1, dx, dy;
char buf[80];
- int shift = button & MOD_SHFT, control = button & MOD_CTRL,
- pad = button & MOD_NUM_KEYPAD;
+ bool shift = button & MOD_SHFT, control = button & MOD_CTRL;
+ int pad = button & MOD_NUM_KEYPAD;
button &= ~MOD_MASK;
if (IS_CURSOR_MOVE(button) || pad) {
if (!ui->cur_visible) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
ui->cur_y = y - 1;
}
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
}
if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
cx = FROMCOORD(x);
cy = FROMCOORD(y);
- ui->cur_visible = 0;
+ ui->cur_visible = false;
} else if (IS_CURSOR_SELECT(button)) {
if (ui->cur_visible) {
if (ui->cur_x == -1 || ui->cur_x == state->w ||
return UI_UPDATE;
}
} else {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
} else {
ret->completed = ret->movecount;
for (n = 0; n < ret->n; n++)
if (ret->tiles[n] != n+1)
- ret->completed = false;
+ ret->completed = 0;
}
return ret;
}
static void draw_arrow(drawing *dr, game_drawstate *ds,
- int x, int y, int xdx, int xdy, int cur)
+ int x, int y, int xdx, int xdy, bool cur)
{
int coords[14];
int ydy = -xdx, ydx = xdy;
}
static void draw_arrow_for_cursor(drawing *dr, game_drawstate *ds,
- int cur_x, int cur_y, int cur)
+ int cur_x, int cur_y, bool cur)
{
if (cur_x == -1 && cur_y == -1)
return; /* 'no cursur here */
* Arrows for making moves.
*/
for (i = 0; i < state->w; i++) {
- draw_arrow(dr, ds, COORD(i), COORD(0), +1, 0, 0);
- draw_arrow(dr, ds, COORD(i+1), COORD(state->h), -1, 0, 0);
+ draw_arrow(dr, ds, COORD(i), COORD(0), +1, 0, false);
+ draw_arrow(dr, ds, COORD(i+1), COORD(state->h), -1, 0, false);
}
for (i = 0; i < state->h; i++) {
- draw_arrow(dr, ds, COORD(state->w), COORD(i), 0, +1, 0);
- draw_arrow(dr, ds, COORD(0), COORD(i+1), 0, -1, 0);
+ draw_arrow(dr, ds, COORD(state->w), COORD(i), 0, +1, false);
+ draw_arrow(dr, ds, COORD(0), COORD(i+1), 0, -1, false);
}
ds->started = true;
if (cur_x != ds->cur_x || cur_y != ds->cur_y) {
/* Cursor has changed; redraw two (prev and curr) arrows. */
- draw_arrow_for_cursor(dr, ds, cur_x, cur_y, 1);
- draw_arrow_for_cursor(dr, ds, ds->cur_x, ds->cur_y, 0);
+ draw_arrow_for_cursor(dr, ds, cur_x, cur_y, true);
+ draw_arrow_for_cursor(dr, ds, ds->cur_x, ds->cur_y, false);
}
/*
*/
#if defined STANDALONE_SOLVER
#define SOLVER_DIAGNOSTICS
-int verbose = false;
+bool verbose = false;
#elif defined SOLVER_DIAGNOSTICS
#define verbose true
#endif
game_clues *clues;
signed char *soln;
unsigned char *errors;
- int completed;
- int used_solve; /* used to suppress completion flash */
+ bool completed;
+ bool used_solve; /* used to suppress completion flash */
};
static game_params *default_params(void)
* Tracks whether each connected set of points includes a
* border point.
*/
- unsigned char *border;
+ bool *border;
/*
* Another disjoint set forest. This one tracks _squares_ which
struct solver_scratch *ret = snew(struct solver_scratch);
ret->connected = snewn(W*H, int);
ret->exits = snewn(W*H, int);
- ret->border = snewn(W*H, unsigned char);
+ ret->border = snewn(W*H, bool);
ret->equiv = snewn(w*h, int);
ret->slashval = snewn(w*h, signed char);
ret->vbitmap = snewn(w*h, unsigned char);
static void merge_vertices(int *connected,
struct solver_scratch *sc, int i, int j)
{
- int exits = -1, border = false; /* initialise to placate optimiser */
+ int exits = -1;
+ bool border = false; /* initialise to placate optimiser */
if (sc) {
i = dsf_canonify(connected, i);
}
}
-static int vbitmap_clear(int w, int h, struct solver_scratch *sc,
- int x, int y, int vbits, const char *reason, ...)
+static bool vbitmap_clear(int w, int h, struct solver_scratch *sc,
+ int x, int y, int vbits, const char *reason, ...)
{
- int done_something = false;
+ bool done_something = false;
int vbit;
for (vbit = 1; vbit <= 8; vbit <<= 1)
{
int W = w+1, H = h+1;
int x, y, i, j;
- int done_something;
+ bool done_something;
/*
* Clear the output.
*/
for (y = 0; y < h; y++)
for (x = 0; x < w; x++) {
- int fs, bs, v;
- int c1, c2;
+ bool fs, bs;
+ int v, c1, c2;
#ifdef SOLVER_DIAGNOSTICS
const char *reason = "<internal error>";
#endif
* Fill in each one in turn.
*/
for (i = 0; i < w*h; i++) {
- int fs, bs, v;
+ bool fs, bs;
+ int v;
y = indices[i] / w;
x = indices[i] % w;
shuffle(clueindices, W*H, sizeof(*clueindices), rs);
for (j = 0; j < 2; j++) {
for (i = 0; i < W*H; i++) {
- int pass, yb, xb;
+ int pass;
+ bool yb, xb;
y = clueindices[i] / W;
x = clueindices[i] % W;
* squares that contributed to it.
*/
static int vertex_degree(int w, int h, signed char *soln, int x, int y,
- int anti, int *sx, int *sy)
+ bool anti, int *sx, int *sy)
{
int ret = 0;
return -1;
}
-static int check_completion(game_state *state)
+static bool check_completion(game_state *state)
{
int w = state->p.w, h = state->p.h, W = w+1, H = h+1;
- int x, y, err = false;
+ int x, y;
+ bool err = false;
memset(state->errors, 0, W*H);
int w = state->p.w, h = state->p.h;
signed char *soln;
int bs, ret;
- int free_soln = false;
+ bool free_soln = false;
char *move, buf[80];
int movelen, movesize;
int x, y;
}
struct game_ui {
- int cur_x, cur_y, cur_visible;
+ int cur_x, cur_y;
+ bool cur_visible;
};
static game_ui *new_ui(const game_state *state)
{
game_ui *ui = snew(game_ui);
- ui->cur_x = ui->cur_y = ui->cur_visible = 0;
+ ui->cur_x = ui->cur_y = 0;
+ ui->cur_visible = false;
return ui;
}
struct game_drawstate {
int tilesize;
- int started;
+ bool started;
long *grid;
long *todraw;
};
y = FROMCOORD(y);
if (x < 0 || y < 0 || x >= w || y >= h)
return NULL;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
} else if (IS_CURSOR_SELECT(button)) {
if (!ui->cur_visible) {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
x = ui->cur_x;
action = (button == CURSOR_SELECT2) ? ANTICLOCKWISE : CLOCKWISE;
} else if (IS_CURSOR_MOVE(button)) {
- move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, 0);
- ui->cur_visible = 1;
+ move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, false);
+ ui->cur_visible = true;
return UI_UPDATE;
} else if (button == '\\' || button == '\b' || button == '/') {
int x = ui->cur_x, y = ui->cur_y;
}
static void draw_clue(drawing *dr, game_drawstate *ds,
- int x, int y, long v, long err, int bg, int colour)
+ int x, int y, long v, bool err, int bg, int colour)
{
char p[2];
int ccol = colour >= 0 ? colour : ((x ^ y) & 1) ? COL_SLANT1 : COL_SLANT2;
{
int w = state->p.w, h = state->p.h, W = w+1, H = h+1;
int x, y;
- int flashing;
+ bool flashing;
if (flashtime > 0)
flashing = (int)(flashtime * 3 / FLASH_TIME) != 1;
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
- int err = state->errors[y*W+x] & ERR_SQUARE;
+ bool err = state->errors[y*W+x] & ERR_SQUARE;
if (state->soln[y*w+x] < 0) {
ds->todraw[(y+1)*(w+2)+(x+1)] |= BACKSLASH;
game_state *s;
char *id = NULL, *desc;
const char *err;
- int grade = false;
- int ret, diff, really_verbose = false;
+ bool grade = false;
+ int ret, diff;
+ bool really_verbose = false;
struct solver_scratch *sc;
while (--argc > 0) {
* compositeness - a 7x7 jigsaw sudoku makes perfect sense).
*/
int c, r, symm, diff, kdiff;
- int xtype; /* require all digits in X-diagonals */
- int killer;
+ bool xtype; /* require all digits in X-diagonals */
+ bool killer;
};
struct block_structure {
int cr;
struct block_structure *blocks;
struct block_structure *kblocks; /* Blocks for killer puzzles. */
- int xtype, killer;
+ bool xtype, killer;
digit *grid, *kgrid;
- unsigned char *pencil; /* c*r*c*r elements */
- unsigned char *immutable; /* marks which digits are clues */
- int completed, cheated;
+ bool *pencil; /* c*r*c*r elements */
+ bool *immutable; /* marks which digits are clues */
+ bool completed, cheated;
};
static game_params *default_params(void)
static void decode_params(game_params *ret, char const *string)
{
- int seen_r = false;
+ bool seen_r = false;
ret->c = ret->r = atoi(string);
ret->xtype = false;
string++;
ret->killer = true;
} else if (*string == 'r' || *string == 'm' || *string == 'a') {
- int sn, sc, sd;
+ int sn, sc;
+ bool sd;
sc = *string++;
if (sc == 'm' && *string == 'd') {
sd = true;
* The way to index this array is cube[(y*cr+x)*cr+n-1]; there
* are macros below to help with this.
*/
- unsigned char *cube;
+ bool *cube;
/*
* This is the grid in which we write down our final
* deductions. y-coordinates in here are _not_ transformed.
* many times.
*/
/* row[y*cr+n-1] true if digit n has been placed in row y */
- unsigned char *row;
+ bool *row;
/* col[x*cr+n-1] true if digit n has been placed in row x */
- unsigned char *col;
+ bool *col;
/* blk[i*cr+n-1] true if digit n has been placed in block i */
- unsigned char *blk;
+ bool *blk;
/* diag[i*cr+n-1] true if digit n has been placed in diagonal i */
- unsigned char *diag; /* diag 0 is \, 1 is / */
+ bool *diag; /* diag 0 is \, 1 is / */
int *regions;
int nr_regions;
}
#endif
ret = +1; /* we did something */
- usage->cube[p] = 0;
+ usage->cube[p] = false;
}
}
* any row with a solitary 1 - and discarding that row and the
* column containing the 1.
*/
- memset(rowidx, true, cr);
- memset(colidx, true, cr);
+ memset(rowidx, 1, cr);
+ memset(colidx, 1, cr);
for (i = 0; i < cr; i++) {
int count = 0, first = -1;
for (j = 0; j < cr; j++)
return -1;
}
if (count == 1)
- rowidx[i] = colidx[first] = false;
+ rowidx[i] = colidx[first] = 0;
}
/*
*/
int rows = 0;
for (i = 0; i < n; i++) {
- int ok = true;
+ bool ok = true;
for (j = 0; j < n; j++)
if (set[j] && grid[i*cr+j]) {
ok = false;
}
if (rows >= n - count) {
- int progress = false;
+ bool progress = false;
/*
* We've got one! Now, for each row which _doesn't_
* positions in the cube to meddle with.
*/
for (i = 0; i < n; i++) {
- int ok = true;
+ bool ok = true;
for (j = 0; j < n; j++)
if (set[j] && grid[i*cr+j]) {
ok = false;
static int solver_killer_sums(struct solver_usage *usage, int b,
struct block_structure *cages, int clue,
- int cage_is_region
+ bool cage_is_region
#ifdef STANDALONE_SOLVER
, const char *cage_type
#endif
};
static void solver(int cr, struct block_structure *blocks,
- struct block_structure *kblocks, int xtype,
+ struct block_structure *kblocks, bool xtype,
digit *grid, digit *kgrid, struct difficulty *dlev)
{
struct solver_usage *usage;
usage->kblocks = usage->extra_cages = NULL;
usage->extra_clues = NULL;
}
- usage->cube = snewn(cr*cr*cr, unsigned char);
+ usage->cube = snewn(cr*cr*cr, bool);
usage->grid = grid; /* write straight back to the input */
if (kgrid) {
int nclues;
usage->kclues = NULL;
}
- memset(usage->cube, true, cr*cr*cr);
+ for (i = 0; i < cr*cr*cr; i++)
+ usage->cube[i] = true;
- usage->row = snewn(cr * cr, unsigned char);
- usage->col = snewn(cr * cr, unsigned char);
- usage->blk = snewn(cr * cr, unsigned char);
- memset(usage->row, false, cr * cr);
- memset(usage->col, false, cr * cr);
- memset(usage->blk, false, cr * cr);
+ usage->row = snewn(cr * cr, bool);
+ usage->col = snewn(cr * cr, bool);
+ usage->blk = snewn(cr * cr, bool);
+ memset(usage->row, 0, cr * cr * sizeof(bool));
+ memset(usage->col, 0, cr * cr * sizeof(bool));
+ memset(usage->blk, 0, cr * cr * sizeof(bool));
if (xtype) {
- usage->diag = snewn(cr * 2, unsigned char);
- memset(usage->diag, false, cr * 2);
+ usage->diag = snewn(cr * 2, bool);
+ memset(usage->diag, 0, cr * 2 * sizeof(bool));
} else
usage->diag = NULL;
}
if (usage->kclues != NULL) {
- int changed = false;
+ bool changed = false;
/*
* First, bring the kblocks into a more useful form: remove
}
}
if (dlev->maxkdiff >= DIFF_KINTERSECT && usage->kclues != NULL) {
- int changed = false;
+ bool changed = false;
/*
* Now, create the extra_cages information. Every full region
* (row, column, or block) has the same sum total (45 for 3x3
* implement it for a higher difficulty level.
*/
if (dlev->maxkdiff >= DIFF_KMINMAX && usage->kclues != NULL) {
- int changed = false;
+ bool changed = false;
for (b = 0; b < usage->kblocks->nr_blocks; b++) {
int ret = solver_killer_minmax(usage, usage->kblocks,
usage->kclues, b
* This can only be used if a cage lies entirely within a region.
*/
if (dlev->maxkdiff >= DIFF_KSUMS && usage->kclues != NULL) {
- int changed = false;
+ bool changed = false;
for (b = 0; b < usage->kblocks->nr_blocks; b++) {
int ret = solver_killer_sums(usage, b, usage->kblocks,
* Return values: 1 means solution found, 0 means no solution
* found on this branch.
*/
-static int gridgen_real(struct gridgen_usage *usage, digit *grid, int *steps)
+static bool gridgen_real(struct gridgen_usage *usage, digit *grid, int *steps)
{
int cr = usage->cr;
- int i, j, n, sx, sy, bestm, bestr, ret;
+ int i, j, n, sx, sy, bestm, bestr;
+ bool ret;
int *digits;
unsigned int used;
* Entry point to generator. You give it parameters and a starting
* grid, which is simply an array of cr*cr digits.
*/
-static int gridgen(int cr, struct block_structure *blocks,
- struct block_structure *kblocks, int xtype,
- digit *grid, random_state *rs, int maxsteps)
+static bool gridgen(int cr, struct block_structure *blocks,
+ struct block_structure *kblocks, bool xtype,
+ digit *grid, random_state *rs, int maxsteps)
{
struct gridgen_usage *usage;
- int x, y, ret;
+ int x, y;
+ bool ret;
/*
* Clear the grid to start with.
if (kblocks != NULL) {
usage->kblocks = kblocks;
usage->cge = snewn(usage->kblocks->nr_blocks, unsigned int);
- memset(usage->cge, false, kblocks->nr_blocks * sizeof *usage->cge);
+ memset(usage->cge, 0, kblocks->nr_blocks * sizeof *usage->cge);
} else {
usage->cge = NULL;
}
/*
* Check whether a grid contains a valid complete puzzle.
*/
-static int check_valid(int cr, struct block_structure *blocks,
- struct block_structure *kblocks,
- digit *kgrid, int xtype, digit *grid)
+static bool check_valid(int cr, struct block_structure *blocks,
+ struct block_structure *kblocks,
+ digit *kgrid, bool xtype, digit *grid)
{
- unsigned char *used;
+ bool *used;
int x, y, i, j, n;
- used = snewn(cr, unsigned char);
+ used = snewn(cr, bool);
/*
* Check that each row contains precisely one of everything.
*/
for (y = 0; y < cr; y++) {
- memset(used, false, cr);
+ memset(used, 0, cr * sizeof(bool));
for (x = 0; x < cr; x++)
if (grid[y*cr+x] > 0 && grid[y*cr+x] <= cr)
used[grid[y*cr+x]-1] = true;
* Check that each column contains precisely one of everything.
*/
for (x = 0; x < cr; x++) {
- memset(used, false, cr);
+ memset(used, 0, cr * sizeof(bool));
for (y = 0; y < cr; y++)
if (grid[y*cr+x] > 0 && grid[y*cr+x] <= cr)
used[grid[y*cr+x]-1] = true;
* Check that each block contains precisely one of everything.
*/
for (i = 0; i < cr; i++) {
- memset(used, false, cr);
+ memset(used, 0, cr * sizeof(bool));
for (j = 0; j < cr; j++)
if (grid[blocks->blocks[i][j]] > 0 &&
grid[blocks->blocks[i][j]] <= cr)
*/
if (kblocks) {
for (i = 0; i < kblocks->nr_blocks; i++) {
- memset(used, false, cr);
+ memset(used, 0, cr * sizeof(bool));
for (j = 0; j < kblocks->nr_squares[i]; j++)
if (grid[kblocks->blocks[i][j]] > 0 &&
grid[kblocks->blocks[i][j]] <= cr) {
* Check that each diagonal contains precisely one of everything.
*/
if (xtype) {
- memset(used, false, cr);
+ memset(used, 0, cr * sizeof(bool));
for (i = 0; i < cr; i++)
if (grid[diag0(i)] > 0 && grid[diag0(i)] <= cr)
used[grid[diag0(i)]-1] = true;
return false;
}
- memset(used, false, cr);
+ memset(used, 0, cr * sizeof(bool));
for (i = 0; i < cr; i++)
if (grid[diag1(i)] > 0 && grid[diag1(i)] <= cr)
used[grid[diag1(i)]-1] = true;
* etc).
*/
for (i = 0; i <= 2*cr*(cr-1); i++) {
- int x, y, p0, p1, edge;
+ int x, y, p0, p1;
+ bool edge;
if (i == 2*cr*(cr-1)) {
edge = true; /* terminating virtual edge */
b->nr_blocks = n1;
}
-static int merge_some_cages(struct block_structure *b, int cr, int area,
+static bool merge_some_cages(struct block_structure *b, int cr, int area,
digit *grid, random_state *rs)
{
/*
}
static struct block_structure *gen_killer_cages(int cr, random_state *rs,
- int remove_singletons)
+ bool remove_singletons)
{
int nr;
int x, y, area = cr * cr;
*pdsf = dsf = snew_dsf(area);
while (*desc && *desc != ',') {
- int c, adv;
+ int c;
+ bool adv;
if (*desc == '_')
c = 0;
state->killer = params->killer;
state->grid = snewn(area, digit);
- state->pencil = snewn(area * cr, unsigned char);
- memset(state->pencil, 0, area * cr);
- state->immutable = snewn(area, unsigned char);
- memset(state->immutable, false, area);
+ state->pencil = snewn(area * cr, bool);
+ memset(state->pencil, 0, area * cr * sizeof(bool));
+ state->immutable = snewn(area, bool);
+ memset(state->immutable, 0, area * sizeof(bool));
state->blocks = alloc_block_structure (c, r, area, cr, cr);
} else
ret->kgrid = NULL;
- ret->pencil = snewn(area * cr, unsigned char);
- memcpy(ret->pencil, state->pencil, area * cr);
+ ret->pencil = snewn(area * cr, bool);
+ memcpy(ret->pencil, state->pencil, area * cr * sizeof(bool));
- ret->immutable = snewn(area, unsigned char);
- memcpy(ret->immutable, state->immutable, area);
+ ret->immutable = snewn(area, bool);
+ memcpy(ret->immutable, state->immutable, area * sizeof(bool));
ret->completed = state->completed;
ret->cheated = state->cheated;
}
static char *grid_text_format(int cr, struct block_structure *blocks,
- int xtype, digit *grid)
+ bool xtype, digit *grid)
{
int vmod, hmod;
int x, y;
* This indicates whether the current highlight is a
* pencil-mark one or a real one.
*/
- int hpencil;
+ bool hpencil;
/*
* This indicates whether or not we're showing the highlight
* (used to be hx = hy = -1); important so that when we're
* using the cursor keys it doesn't keep coming back at a
- * fixed position. When hshow = 1, pressing a valid number
+ * fixed position. When hshow is true, pressing a valid number
* or letter key or Space will enter that number or letter in the grid.
*/
- int hshow;
+ bool hshow;
/*
* This indicates whether we're using the highlight as a cursor;
* it means that it doesn't vanish on a keypress, and that it is
* allowed on immutable squares.
*/
- int hcursor;
+ bool hcursor;
};
static game_ui *new_ui(const game_state *state)
game_ui *ui = snew(game_ui);
ui->hx = ui->hy = 0;
- ui->hpencil = ui->hshow = ui->hcursor = 0;
+ ui->hpencil = false;
+ ui->hshow = false;
+ ui->hcursor = false;
return ui;
}
*/
if (ui->hshow && ui->hpencil && !ui->hcursor &&
newstate->grid[ui->hy * cr + ui->hx] != 0) {
- ui->hshow = 0;
+ ui->hshow = false;
}
}
struct game_drawstate {
- int started;
- int cr, xtype;
+ bool started, xtype;
+ int cr;
int tilesize;
digit *grid;
unsigned char *pencil;
if (tx >= 0 && tx < cr && ty >= 0 && ty < cr) {
if (button == LEFT_BUTTON) {
if (state->immutable[ty*cr+tx]) {
- ui->hshow = 0;
+ ui->hshow = false;
} else if (tx == ui->hx && ty == ui->hy &&
- ui->hshow && ui->hpencil == 0) {
- ui->hshow = 0;
+ ui->hshow && !ui->hpencil) {
+ ui->hshow = false;
} else {
ui->hx = tx;
ui->hy = ty;
- ui->hshow = 1;
- ui->hpencil = 0;
+ ui->hshow = true;
+ ui->hpencil = false;
}
- ui->hcursor = 0;
+ ui->hcursor = false;
return UI_UPDATE;
}
if (button == RIGHT_BUTTON) {
if (state->grid[ty*cr+tx] == 0) {
if (tx == ui->hx && ty == ui->hy &&
ui->hshow && ui->hpencil) {
- ui->hshow = 0;
+ ui->hshow = false;
} else {
- ui->hpencil = 1;
+ ui->hpencil = true;
ui->hx = tx;
ui->hy = ty;
- ui->hshow = 1;
+ ui->hshow = true;
}
} else {
- ui->hshow = 0;
+ ui->hshow = false;
}
- ui->hcursor = 0;
+ ui->hcursor = false;
return UI_UPDATE;
}
}
if (IS_CURSOR_MOVE(button)) {
- move_cursor(button, &ui->hx, &ui->hy, cr, cr, 0);
- ui->hshow = ui->hcursor = 1;
+ move_cursor(button, &ui->hx, &ui->hy, cr, cr, false);
+ ui->hshow = true;
+ ui->hcursor = true;
return UI_UPDATE;
}
if (ui->hshow &&
(button == CURSOR_SELECT)) {
- ui->hpencil = 1 - ui->hpencil;
- ui->hcursor = 1;
+ ui->hpencil = !ui->hpencil;
+ ui->hcursor = true;
return UI_UPDATE;
}
sprintf(buf, "%c%d,%d,%d",
(char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n);
- if (!ui->hcursor) ui->hshow = 0;
+ if (!ui->hcursor) ui->hshow = false;
return dupstr(buf);
}
for (y = 0; y < cr; y++) {
for (x = 0; x < cr; x++) {
if (!ret->grid[y*cr+x]) {
- memset(ret->pencil + (y*cr+x)*cr, 1, cr);
+ int i;
+ for (i = 0; i < cr; i++)
+ ret->pencil[(y*cr+x)*cr + i] = true;
}
}
}
int t = GRIDEXTRA * 3;
int kcx, kcy, kcw, kch;
int kl, kt, kr, kb;
- int has_left = 0, has_right = 0, has_top = 0, has_bottom = 0;
+ bool has_left = false, has_right = false;
+ bool has_top = false, has_bottom = false;
/*
* In non-jigsaw mode, the Killer cages are placed at a
* different areas.
*/
if (x == 0 || state->kblocks->whichblock[y*cr+x] != state->kblocks->whichblock[y*cr+x-1])
- has_left = 1, kl += t;
+ has_left = true, kl += t;
if (x+1 >= cr || state->kblocks->whichblock[y*cr+x] != state->kblocks->whichblock[y*cr+x+1])
- has_right = 1, kr -= t;
+ has_right = true, kr -= t;
if (y == 0 || state->kblocks->whichblock[y*cr+x] != state->kblocks->whichblock[(y-1)*cr+x])
- has_top = 1, kt += t;
+ has_top = true, kt += t;
if (y+1 >= cr || state->kblocks->whichblock[y*cr+x] != state->kblocks->whichblock[(y+1)*cr+x])
- has_bottom = 1, kb -= t;
+ has_bottom = true, kb -= t;
if (has_top)
draw_line(dr, kl, kt, kr, kt, col_killer);
if (has_bottom)
game_state *s;
char *id = NULL, *desc;
const char *err;
- int grade = false;
+ bool grade = false;
struct difficulty dlev;
while (--argc > 0) {
int n;
int *queue;
int ip, op; /* in pointer, out pointer */
- char *flags;
+ bool *flags;
};
tdq *tdq_new(int n)
int i;
tdq *tdq = snew(struct tdq);
tdq->queue = snewn(n, int);
- tdq->flags = snewn(n, char);
+ tdq->flags = snewn(n, bool);
for (i = 0; i < n; i++) {
tdq->queue[i] = 0;
- tdq->flags[i] = 0;
+ tdq->flags[i] = false;
}
tdq->n = n;
tdq->ip = tdq->op = 0;
assert((unsigned)k < (unsigned)tdq->n);
if (!tdq->flags[k]) {
tdq->queue[tdq->ip] = k;
- tdq->flags[k] = 1;
+ tdq->flags[k] = true;
if (++tdq->ip == tdq->n)
tdq->ip = 0;
}
if (!tdq->flags[ret])
return -1;
- tdq->flags[ret] = 0;
+ tdq->flags[ret] = false;
if (++tdq->op == tdq->n)
tdq->op = 0;
*/
#if defined STANDALONE_SOLVER
#define SOLVER_DIAGNOSTICS
-int verbose = false;
+bool verbose = false;
#elif defined SOLVER_DIAGNOSTICS
#define verbose true
#endif
game_params p;
char *grid;
struct numbers *numbers;
- int completed, used_solve;
+ bool completed, used_solve;
};
static game_params *default_params(void)
* Main solver loop.
*/
while (1) {
- int done_something = false;
+ bool done_something = false;
/*
* Any tent which has only one unattached tree adjacent to
for (y = 0; y < h; y++)
for (x = 0; x < w; x++)
if (soln[y*w+x] == BLANK) {
- int can_be_tent = false;
+ bool can_be_tent = false;
for (d = 1; d < MAXDIR; d++) {
int x2 = x + dx(d), y2 = y + dy(d);
for (y = 0; y < h; y++)
for (x = 0; x < w; x++)
if (soln[y*w+x] == BLANK) {
- int dx, dy, imposs = false;
+ int dx, dy;
+ bool imposs = false;
for (dy = -1; dy <= +1; dy++)
for (dx = -1; dx <= +1; dx++)
* And iterate over all possibilities.
*/
while (1) {
- int p, valid;
+ int p;
+ bool valid;
/*
* See if this possibility is valid. The only way
* is too few to fit the remaining tents into. */
for (i = 0; j > 0 && i+j <= w*h; i++) {
int which, x, y, d, tmp;
- int dy, dx, ok = true;
+ int dy, dx;
+ bool ok = true;
which = i + random_upto(rs, j);
tmp = order[which];
p = ret;
j = 0;
for (i = 0; i <= w*h; i++) {
- int c = (i < w*h ? grid[i] == TREE : 1);
+ bool c = (i < w*h ? grid[i] == TREE : true);
if (c) {
*p++ = (j == 0 ? '_' : j-1 + 'a');
j = 0;
int dsx, dsy; /* coords of drag start */
int dex, dey; /* coords of drag end */
int drag_button; /* -1 for none, or a button code */
- int drag_ok; /* dragged off the window, to cancel */
+ bool drag_ok; /* dragged off the window, to cancel */
- int cx, cy, cdisp; /* cursor position, and ?display. */
+ int cx, cy; /* cursor position. */
+ bool cdisp; /* is cursor displayed? */
};
static game_ui *new_ui(const game_state *state)
ui->dex = ui->dey = -1;
ui->drag_button = -1;
ui->drag_ok = false;
- ui->cx = ui->cy = ui->cdisp = 0;
+ ui->cx = ui->cy = 0;
+ ui->cdisp = false;
return ui;
}
struct game_drawstate {
int tilesize;
- int started;
+ bool started;
game_params p;
int *drawn, *numbersdrawn;
int cx, cy; /* last-drawn cursor pos, or (-1,-1) if absent. */
{
int w = state->p.w, h = state->p.h;
char tmpbuf[80];
- int shift = button & MOD_SHFT, control = button & MOD_CTRL;
+ bool shift = button & MOD_SHFT, control = button & MOD_CTRL;
button &= ~MOD_MASK;
ui->dsx = ui->dex = x;
ui->dsy = ui->dey = y;
ui->drag_ok = true;
- ui->cdisp = 0;
+ ui->cdisp = false;
return UI_UPDATE;
}
}
if (IS_CURSOR_MOVE(button)) {
- ui->cdisp = 1;
+ ui->cdisp = true;
if (shift || control) {
int len = 0, i, indices[2];
indices[0] = ui->cx + w * ui->cy;
- move_cursor(button, &ui->cx, &ui->cy, w, h, 0);
+ move_cursor(button, &ui->cx, &ui->cy, w, h, false);
indices[1] = ui->cx + w * ui->cy;
/* NONTENTify all unique traversed eligible squares */
tmpbuf[len] = '\0';
if (len) return dupstr(tmpbuf);
} else
- move_cursor(button, &ui->cx, &ui->cy, w, h, 0);
+ move_cursor(button, &ui->cx, &ui->cy, w, h, false);
return UI_UPDATE;
}
if (ui->cdisp) {
return dupstr(tmpbuf);
}
} else if (IS_CURSOR_SELECT(button)) {
- ui->cdisp = 1;
+ ui->cdisp = true;
return UI_UPDATE;
}
}
static void draw_tile(drawing *dr, game_drawstate *ds,
- int x, int y, int v, int cur, int printing)
+ int x, int y, int v, bool cur, bool printing)
{
int err;
int tx = COORD(x), ty = COORD(y);
static void int_redraw(drawing *dr, game_drawstate *ds,
const game_state *oldstate, const game_state *state,
int dir, const game_ui *ui,
- float animtime, float flashtime, int printing)
+ float animtime, float flashtime, bool printing)
{
int w = state->p.w, h = state->p.h;
- int x, y, flashing;
+ int x, y;
+ bool flashing;
int cx = -1, cy = -1;
- int cmoved = 0;
+ bool cmoved = false;
char *tmpgrid;
int *errors;
if (ui) {
if (ui->cdisp) { cx = ui->cx; cy = ui->cy; }
- if (cx != ds->cx || cy != ds->cy) cmoved = 1;
+ if (cx != ds->cx || cy != ds->cy) cmoved = true;
}
if (printing || !ds->started) {
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
int v = state->grid[y*w+x];
- int credraw = 0;
+ bool credraw = false;
/*
* We deliberately do not take drag_ok into account
if (cmoved) {
if ((x == cx && y == cy) ||
- (x == ds->cx && y == ds->cy)) credraw = 1;
+ (x == ds->cx && y == ds->cy)) credraw = true;
}
v |= errors[y*w+x];
game_state *s, *s2;
char *id = NULL, *desc;
const char *err;
- int grade = false;
- int ret, diff, really_verbose = false;
+ bool grade = false;
+ int ret, diff;
+ bool really_verbose = false;
struct solver_scratch *sc;
while (--argc > 0) {
struct game_state {
game_params par;
struct clues *clues;
- unsigned char *clues_done;
+ bool *clues_done;
digit *grid;
int *pencil; /* bitmaps using bits 1<<1..1<<n */
- int completed, cheated;
+ bool completed, cheated;
};
static game_params *default_params(void)
struct solver_ctx {
int w, diff;
- int started;
+ bool started;
int *clues;
long *iscratch;
int *dscratch;
state->clues->clues = snewn(4*w, int);
state->clues->immutable = snewn(a, digit);
state->grid = snewn(a, digit);
- state->clues_done = snewn(4*w, unsigned char);
+ state->clues_done = snewn(4*w, bool);
state->pencil = snewn(a, int);
for (i = 0; i < a; i++) {
}
memset(state->clues->immutable, 0, a);
- memset(state->clues_done, 0, 4*w*sizeof(unsigned char));
+ memset(state->clues_done, 0, 4*w*sizeof(bool));
for (i = 0; i < 4*w; i++) {
if (i > 0) {
}
assert(!*p);
- state->completed = state->cheated = false;
+ state->completed = false;
+ state->cheated = false;
return state;
}
ret->grid = snewn(a, digit);
ret->pencil = snewn(a, int);
- ret->clues_done = snewn(4*w, unsigned char);
+ ret->clues_done = snewn(4*w, bool);
memcpy(ret->grid, state->grid, a*sizeof(digit));
memcpy(ret->pencil, state->pencil, a*sizeof(int));
- memcpy(ret->clues_done, state->clues_done, 4*w*sizeof(unsigned char));
+ memcpy(ret->clues_done, state->clues_done, 4*w*sizeof(bool));
ret->completed = state->completed;
ret->cheated = state->cheated;
* This indicates whether the current highlight is a
* pencil-mark one or a real one.
*/
- int hpencil;
+ bool hpencil;
/*
* This indicates whether or not we're showing the highlight
* (used to be hx = hy = -1); important so that when we're
* fixed position. When hshow = 1, pressing a valid number
* or letter key or Space will enter that number or letter in the grid.
*/
- int hshow;
+ bool hshow;
/*
* This indicates whether we're using the highlight as a cursor;
* it means that it doesn't vanish on a keypress, and that it is
* allowed on immutable squares.
*/
- int hcursor;
+ bool hcursor;
};
static game_ui *new_ui(const game_state *state)
game_ui *ui = snew(game_ui);
ui->hx = ui->hy = 0;
- ui->hpencil = ui->hshow = ui->hcursor = 0;
+ ui->hpencil = false;
+ ui->hshow = false;
+ ui->hcursor = false;
return ui;
}
*/
if (ui->hshow && ui->hpencil && !ui->hcursor &&
newstate->grid[ui->hy * w + ui->hx] != 0) {
- ui->hshow = 0;
+ ui->hshow = false;
}
}
struct game_drawstate {
int tilesize;
- int three_d; /* default 3D graphics are user-disableable */
- int started;
+ bool three_d; /* default 3D graphics are user-disableable */
+ bool started;
long *tiles; /* (w+2)*(w+2) temp space */
long *drawn; /* (w+2)*(w+2)*4: current drawn data */
- int *errtmp;
+ bool *errtmp;
};
-static int check_errors(const game_state *state, int *errors)
+static bool check_errors(const game_state *state, bool *errors)
{
int w = state->par.w /*, a = w*w */;
int W = w+2, A = W*W; /* the errors array is (w+2) square */
int *clues = state->clues->clues;
digit *grid = state->grid;
- int i, x, y, errs = false;
+ int i, x, y;
+ bool errs = false;
int tmp[32];
assert(w < lenof(tmp));
if (errors)
for (i = 0; i < A; i++)
- errors[i] = 0;
+ errors[i] = false;
for (y = 0; y < w; y++) {
unsigned long mask = 0, errmask = 0;
return -1;
}
-static int is_clue(const game_state *state, int x, int y)
+static bool is_clue(const game_state *state, int x, int y)
{
int w = state->par.w;
int x, int y, int button)
{
int w = state->par.w;
- int shift_or_control = button & (MOD_SHFT | MOD_CTRL);
+ bool shift_or_control = button & (MOD_SHFT | MOD_CTRL);
int tx, ty;
char buf[80];
if (tx >= 0 && tx < w && ty >= 0 && ty < w) {
if (button == LEFT_BUTTON) {
if (tx == ui->hx && ty == ui->hy &&
- ui->hshow && ui->hpencil == 0) {
- ui->hshow = 0;
+ ui->hshow && !ui->hpencil) {
+ ui->hshow = false;
} else {
ui->hx = tx;
ui->hy = ty;
ui->hshow = !state->clues->immutable[ty*w+tx];
- ui->hpencil = 0;
+ ui->hpencil = false;
}
- ui->hcursor = 0;
+ ui->hcursor = false;
return UI_UPDATE;
}
if (button == RIGHT_BUTTON) {
if (state->grid[ty*w+tx] == 0) {
if (tx == ui->hx && ty == ui->hy &&
ui->hshow && ui->hpencil) {
- ui->hshow = 0;
+ ui->hshow = false;
} else {
- ui->hpencil = 1;
+ ui->hpencil = true;
ui->hx = tx;
ui->hy = ty;
- ui->hshow = 1;
+ ui->hshow = true;
}
} else {
- ui->hshow = 0;
+ ui->hshow = false;
}
- ui->hcursor = 0;
+ ui->hcursor = false;
return UI_UPDATE;
}
} else if (button == LEFT_BUTTON) {
}
return NULL;
}
- move_cursor(button, &ui->hx, &ui->hy, w, w, 0);
- ui->hshow = ui->hcursor = 1;
+ move_cursor(button, &ui->hx, &ui->hy, w, w, false);
+ ui->hshow = true;
+ ui->hcursor = true;
return UI_UPDATE;
}
if (ui->hshow &&
(button == CURSOR_SELECT)) {
- ui->hpencil = 1 - ui->hpencil;
- ui->hcursor = 1;
+ ui->hpencil = !ui->hpencil;
+ ui->hcursor = true;
return UI_UPDATE;
}
sprintf(buf, "%c%d,%d,%d",
(char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n);
- if (!ui->hcursor) ui->hshow = 0;
+ if (!ui->hcursor) ui->hshow = false;
return dupstr(buf);
}
ds->drawn = snewn((w+2)*(w+2)*4, long);
for (i = 0; i < (w+2)*(w+2)*4; i++)
ds->drawn[i] = -1;
- ds->errtmp = snewn((w+2)*(w+2), int);
+ ds->errtmp = snewn((w+2)*(w+2), bool);
return ds;
}
game_state *s;
char *id = NULL, *desc;
const char *err;
- int grade = false;
- int ret, diff, really_show_working = false;
+ bool grade = false;
+ int ret, diff;
+ bool really_show_working = false;
while (--argc > 0) {
char *p = *++argv;
* the puzzle internally before doing anything else.
*/
ret = -1; /* placate optimiser */
- solver_show_working = false;
+ solver_show_working = 0;
for (diff = 0; diff < DIFFCOUNT; diff++) {
memcpy(s->grid, s->clues->immutable, p->w * p->w);
ret = solver(p->w, s->clues->clues, s->grid, diff);
#define DIFFCONFIG DIFFLIST(CONFIG)
struct game_params {
- int w, h, diff, single_ones;
+ int w, h, diff;
+ bool single_ones;
};
static game_params *default_params(void)
unsigned int *sflags; /* size w*h */
struct numbers *numbers;
int *num_errors; /* size w+h */
- int completed, used_solve, impossible;
+ bool completed, used_solve, impossible;
};
/* Return the four directions in which a particular edge flag is set, around a square. */
return (t ? E_TRACK : 0) | (nt ? E_NOTRACK : 0);
}
-int S_E_ADJ(const game_state *state, int sx, int sy, int d, int *ax, int *ay, unsigned int *ad) {
- if (d == L && sx > 0) { *ax = sx-1; *ay = sy; *ad = R; return 1; }
- if (d == R && sx < state->p.w-1) { *ax = sx+1; *ay = sy; *ad = L; return 1; }
- if (d == U && sy > 0) { *ax = sx; *ay = sy-1; *ad = D; return 1; }
- if (d == D && sy < state->p.h-1) { *ax = sx; *ay = sy+1; *ad = U; return 1; }
+bool S_E_ADJ(const game_state *state, int sx, int sy, int d, int *ax, int *ay, unsigned int *ad) {
+ if (d == L && sx > 0) { *ax = sx-1; *ay = sy; *ad = R; return true; }
+ if (d == R && sx < state->p.w-1) { *ax = sx+1; *ay = sy; *ad = L; return true; }
+ if (d == U && sy > 0) { *ax = sx; *ay = sy-1; *ad = D; return true; }
+ if (d == D && sy < state->p.h-1) { *ax = sx; *ay = sy+1; *ad = U; return true; }
- return 0;
+ return false;
}
/* Sets flag (E_TRACK or E_NOTRACK) on a given edge of a square. */
return 0; /* no possible directions left. */
}
-static int check_completion(game_state *state, int mark);
+static bool check_completion(game_state *state, bool mark);
static void lay_path(game_state *state, random_state *rs)
{
return progress;
}
-static int check_phantom_moves(const game_state *state) {
+static bool check_phantom_moves(const game_state *state) {
int x, y, i;
/* Check that this state won't show 'phantom moves' at the start of the
if (state->sflags[i] & S_CLUE)
continue;
if (S_E_COUNT(state, x, y, E_TRACK) > 1)
- return 1; /* found one! */
+ return true; /* found one! */
}
}
- return 0;
+ return false;
}
static int add_clues(game_state *state, random_state *rs, int diff)
}
if (params->single_ones) {
- int last_was_one = 1, is_one; /* (disallow 1 clue at entry point) */
+ bool last_was_one = true, is_one; /* disallow 1 clue at entry point */
for (i = 0; i < w+h; i++) {
is_one = (state->numbers->numbers[i] == 1);
if (is_one && last_was_one)
static int solve_check_loop_sub(game_state *state, int x, int y, int dir,
int *dsf, int startc, int endc)
{
- int w = state->p.w, h = state->p.h, i = y*w+x, j, k, satisfied = 1;
+ int w = state->p.w, h = state->p.h, i = y*w+x, j, k;
+ bool satisfied = true;
j = (y+DY(dir))*w + (x+DX(dir));
for (k = 0; k < w; k++) {
int target = state->numbers->numbers[k];
int ntracks = solve_count_col(state, k, S_TRACK);
- if (ntracks < target) satisfied = 0;
+ if (ntracks < target) satisfied = false;
}
for (k = 0; k < h; k++) {
int target = state->numbers->numbers[w+k];
int ntracks = solve_count_row(state, k, S_TRACK);
- if (ntracks < target) satisfied = 0;
+ if (ntracks < target) satisfied = false;
}
if (!satisfied) {
return solve_set_eflag(state, x, y, dir, E_NOTRACK,
static int tracks_solve(game_state *state, int diff)
{
- int didsth, x, y, w = state->p.w, h = state->p.h;
+ int x, y, w = state->p.w, h = state->p.h;
+ bool didsth;
debug(("solve..."));
state->impossible = false;
}
while (1) {
- didsth = 0;
+ didsth = false;
- didsth += solve_update_flags(state);
- didsth += solve_count_clues(state);
- didsth += solve_check_loop(state);
+ didsth |= solve_update_flags(state);
+ didsth |= solve_count_clues(state);
+ didsth |= solve_check_loop(state);
if (diff >= DIFF_TRICKY) {
- didsth += solve_check_single(state);
- didsth += solve_check_loose_ends(state);
+ didsth |= solve_check_single(state);
+ didsth |= solve_check_loose_ends(state);
}
if (!didsth || state->impossible) break;
return state->impossible ? -1 : check_completion(state, false) ? 1 : 0;
}
-static char *move_string_diff(const game_state *before, const game_state *after, int issolve)
+static char *move_string_diff(const game_state *before, const game_state *after, bool issolve)
{
int w = after->p.w, h = after->p.h, i, j;
char *move = snewn(w*h*40, char), *p = move;
return -1;
}
-static int check_completion(game_state *state, int mark)
+static bool check_completion(game_state *state, bool mark)
{
- int w = state->p.w, h = state->p.h, x, y, i, target, ret = true;
+ int w = state->p.w, h = state->p.h, x, y, i, target;
+ bool ret = true;
int ntrack, nnotrack, ntrackcomplete;
int *dsf, pathclass;
struct findloopstate *fls;
/* Code borrowed from Pearl. */
struct game_ui {
- int dragging, clearing, notrack;
+ bool dragging, clearing, notrack;
int drag_sx, drag_sy, drag_ex, drag_ey; /* drag start and end grid coords */
int clickx, clicky; /* pixel position of initial click */
int curx, cury; /* grid position of keyboard cursor; uses half-size grid */
- int cursor_active; /* true iff cursor is shown */
+ bool cursor_active; /* true iff cursor is shown */
};
static game_ui *new_ui(const game_state *state)
{
game_ui *ui = snew(game_ui);
- ui->clearing = ui->notrack = ui->dragging = 0;
+ ui->clearing = false;
+ ui->notrack = false;
+ ui->dragging = false;
ui->drag_sx = ui->drag_sy = ui->drag_ex = ui->drag_ey = -1;
ui->cursor_active = false;
ui->curx = ui->cury = 1;
struct game_drawstate {
int sz6, grid_line_all, grid_line_tl, grid_line_br;
- int started;
+ bool started;
int w, h, sz;
unsigned int *flags, *flags_drag;
}
}
-static int ui_can_flip_edge(const game_state *state, int x, int y, int dir,
- int notrack)
+static bool ui_can_flip_edge(const game_state *state, int x, int y, int dir,
+ bool notrack)
{
int w = state->p.w /*, h = state->shared->h, sz = state->shared->sz */;
int x2 = x + DX(dir);
return true;
}
-static int ui_can_flip_square(const game_state *state, int x, int y, int notrack)
+static bool ui_can_flip_square(const game_state *state, int x, int y, bool notrack)
{
int w = state->p.w, trackc;
unsigned sf;
return true;
}
-static char *edge_flip_str(const game_state *state, int x, int y, int dir, int notrack, char *buf) {
+static char *edge_flip_str(const game_state *state, int x, int y, int dir, bool notrack, char *buf) {
unsigned ef = S_E_FLAGS(state, x, y, dir);
char c;
return dupstr(buf);
}
-static char *square_flip_str(const game_state *state, int x, int y, int notrack, char *buf) {
+static char *square_flip_str(const game_state *state, int x, int y, bool notrack, char *buf) {
unsigned f = state->sflags[y*state->p.w+x];
char c;
game_state *dragged = copy_and_apply_drag(state, ui);
char *ret = move_string_diff(state, dragged, false);
- ui->dragging = 0;
+ ui->dragging = false;
free_game(dragged);
return ret;
/* We might still have been dragging (and just done a one-
* square drag): cancel drag, so undo doesn't make it like
* a drag-in-progress. */
- ui->dragging = 0;
+ ui->dragging = false;
/* Click (or tiny drag). Work out which edge we were
* closest to. */
const game_state *state, int dir, const game_ui *ui,
float animtime, float flashtime)
{
- int i, x, y, force = 0, flashing = 0, w = ds->w, h = ds->h;
+ int i, x, y, flashing = 0, w = ds->w, h = ds->h;
+ bool force = false;
game_state *drag_state = NULL;
if (!ds->started) {
draw_update(dr, 0, 0, (w+2)*TILE_SIZE + 2*BORDER, (h+2)*TILE_SIZE + 2*BORDER);
ds->started = true;
- force = 1;
+ force = true;
}
for (i = 0; i < w+h; i++) {
* over to it until it is greater than minimum
* size.
*/
- int undersized = (!sub->elems[0]);
+ bool undersized = (!sub->elems[0]);
LOG((" child %d is %ssize\n", ki,
undersized ? "under" : "minimum-"));
LOG((" neighbour is %s\n",
return ret;
}
tree234 *split234(tree234 *t, void *e, cmpfn234 cmp, int rel) {
- int before;
+ bool before;
int index;
assert(rel != REL234_EQ);
if (rel == REL234_GT || rel == REL234_GE) {
- before = 1;
+ before = true;
rel = (rel == REL234_GT ? REL234_LE : REL234_LT);
} else {
- before = 0;
+ before = false;
}
if (!findrelpos234(t, e, cmp, rel, &index))
index = 0;
tree234 *tree3, *tree4;
for (i = 0; i <= arraylen; i++) {
tree3 = copytree234(tree, NULL, NULL);
- tree4 = splitpos234(tree3, i, 0);
+ tree4 = splitpos234(tree3, i, false);
verifytree(tree3, array, i);
verifytree(tree4, array+i, arraylen-i);
join234(tree3, tree4);
struct game_params {
int w, h, n;
- int rowsonly;
- int orientable;
+ bool rowsonly;
+ bool orientable;
int movetarget;
};
struct game_state {
int w, h, n;
- int orientable;
+ bool orientable;
int *grid;
int completed;
- int used_solve; /* used to suppress completion flash */
+ bool used_solve; /* used to suppress completion flash */
int movecount, movetarget;
int lastx, lasty, lastr; /* coordinates of last rotation */
};
{
ret->w = ret->h = atoi(string);
ret->n = 2;
- ret->rowsonly = ret->orientable = false;
+ ret->rowsonly = false;
+ ret->orientable = false;
ret->movetarget = 0;
while (*string && isdigit((unsigned char)*string)) string++;
if (*string == 'x') {
* the centre is good for a user interface, but too inconvenient to
* use internally.)
*/
-static void do_rotate(int *grid, int w, int h, int n, int orientable,
+static void do_rotate(int *grid, int w, int h, int n, bool orientable,
int x, int y, int dir)
{
int i, j;
}
}
-static int grid_complete(int *grid, int wh, int orientable)
+static bool grid_complete(int *grid, int wh, bool orientable)
{
- int ok = true;
+ bool ok = true;
int i;
for (i = 1; i < wh; i++)
if (grid[i] < grid[i-1])
static char *game_text_format(const game_state *state)
{
char *ret, *p, buf[80];
- int i, x, y, col, o, maxlen;
+ int i, x, y, col, maxlen;
+ bool o = state->orientable;
/*
* First work out how many characters we need to display each
x = sprintf(buf, "%d", state->grid[i] / 4);
if (col < x) col = x;
}
- o = (state->orientable ? 1 : 0);
/*
* Now we know the exact total size of the grid we're going to
struct game_ui {
int cur_x, cur_y;
- int cur_visible;
+ bool cur_visible;
};
static game_ui *new_ui(const game_state *state)
}
struct game_drawstate {
- int started;
+ bool started;
int w, h, bgcolour;
int *grid;
int tilesize;
ui->cur_y--;
if (button == CURSOR_DOWN && (ui->cur_y+n) < (h))
ui->cur_y++;
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
dir = (button == LEFT_BUTTON ? 1 : -1);
if (x < 0 || x > w-n || y < 0 || y > h-n)
return NULL;
- ui->cur_visible = 0;
+ ui->cur_visible = false;
} else if (IS_CURSOR_SELECT(button)) {
if (ui->cur_visible) {
x = ui->cur_x;
y = ui->cur_y;
dir = (button == CURSOR_SELECT2) ? -1 : +1;
} else {
- ui->cur_visible = 1;
+ ui->cur_visible = true;
return UI_UPDATE;
}
} else if (button == 'a' || button == 'A' || button==MOD_NUM_KEYPAD+'7') {
int i, bgcolour;
struct rotation srot, *rot;
int lastx = -1, lasty = -1, lastr = -1;
- int cx, cy, cmoved = 0, n = state->n;
+ int cx, cy, n = state->n;
+ bool cmoved = false;
cx = ui->cur_visible ? ui->cur_x : -state->n;
cy = ui->cur_visible ? ui->cur_y : -state->n;
if (cx != ds->cur_x || cy != ds->cur_y)
- cmoved = 1;
+ cmoved = true;
if (flashtime > 0) {
int frame = (int)(flashtime / FLASH_FRAME);
* Now draw each tile.
*/
for (i = 0; i < state->w * state->h; i++) {
- int t, cc = 0;
+ int t;
+ bool cc = false;
int tx = i % state->w, ty = i / state->w;
/*
if (cmoved) {
/* cursor has moved (or changed visibility)... */
if (tx == cx || tx == cx+n-1 || ty == cy || ty == cy+n-1)
- cc = 1; /* ...we're on new cursor, redraw */
+ cc = true; /* ...we're on new cursor, redraw */
if (tx == ds->cur_x || tx == ds->cur_x+n-1 ||
ty == ds->cur_y || ty == ds->cur_y+n-1)
- cc = 1; /* ...we were on old cursor, redraw */
+ cc = true; /* ...we were on old cursor, redraw */
}
if (ds->bgcolour != bgcolour || /* always redraw when flashing */
struct path *paths;
int *grid;
int *xinfo;
- int *fixed;
+ bool *fixed;
};
struct game_state {
struct game_common *common;
int *guess;
unsigned char *pencils;
- unsigned char *cell_errors;
- unsigned char *hint_errors;
- unsigned char *hints_done;
- unsigned char count_errors[3];
- int solved;
- int cheated;
+ bool *cell_errors;
+ bool *hint_errors;
+ bool *hints_done;
+ bool count_errors[3];
+ bool solved;
+ bool cheated;
};
static game_state *new_state(const game_params *params) {
state->guess = NULL;
state->pencils = NULL;
- state->cell_errors = snewn(state->common->wh, unsigned char);
+ state->cell_errors = snewn(state->common->wh, bool);
for (i=0;i<state->common->wh;i++)
state->cell_errors[i] = false;
- state->hint_errors = snewn(2*state->common->num_paths, unsigned char);
+ state->hint_errors = snewn(2*state->common->num_paths, bool);
for (i=0;i<2*state->common->num_paths;i++)
state->hint_errors[i] = false;
- state->hints_done = snewn(2 * state->common->num_paths, unsigned char);
+ state->hints_done = snewn(2 * state->common->num_paths, bool);
memset(state->hints_done, 0,
- 2 * state->common->num_paths * sizeof(unsigned char));
+ 2 * state->common->num_paths * sizeof(bool));
for (i=0;i<3;i++)
state->count_errors[i] = false;
else ret->pencils = NULL;
if (state->cell_errors != NULL) {
- ret->cell_errors = snewn(ret->common->wh,unsigned char);
+ ret->cell_errors = snewn(ret->common->wh,bool);
memcpy(ret->cell_errors, state->cell_errors,
- ret->common->wh*sizeof(unsigned char));
+ ret->common->wh*sizeof(bool));
}
else ret->cell_errors = NULL;
if (state->hint_errors != NULL) {
- ret->hint_errors = snewn(2*ret->common->num_paths,unsigned char);
+ ret->hint_errors = snewn(2*ret->common->num_paths,bool);
memcpy(ret->hint_errors, state->hint_errors,
- 2*ret->common->num_paths*sizeof(unsigned char));
+ 2*ret->common->num_paths*sizeof(bool));
}
else ret->hint_errors = NULL;
if (state->hints_done != NULL) {
- ret->hints_done = snewn(2 * state->common->num_paths, unsigned char);
+ ret->hints_done = snewn(2 * state->common->num_paths, bool);
memcpy(ret->hints_done, state->hints_done,
- 2 * state->common->num_paths * sizeof(unsigned char));
+ 2 * state->common->num_paths * sizeof(bool));
}
else ret->hints_done = NULL;
for (i=0;i<2*(state->common->params.w + state->common->params.h);i++) {
int x,y,dir;
int j,k,num_monsters;
- int found;
+ bool found;
int c,p;
found = false;
/* Check whether inverse path is already in list */
int *possible;
};
-int next_list(struct guess *g, int pos) {
+bool next_list(struct guess *g, int pos) {
if (pos == 0) {
if ((g->guess[pos] == 1 && g->possible[pos] == 1) ||
view_count[i] = 0;
do {
- int mirror, start_view, end_view;
+ bool mirror;
+ int start_view, end_view;
mirror = false;
start_view = 0;
for (i=0;i<path_guess.length;i++) {
if (state->common->paths[counter].p[p] ==
state->common->paths[counter].mapping[i]) {
- if (path_guess.guess[i] == 1 && mirror == true)
+ if (path_guess.guess[i] == 1 && mirror)
start_view++;
- if (path_guess.guess[i] == 2 && mirror == false)
+ if (path_guess.guess[i] == 2 && !mirror)
start_view++;
if (path_guess.guess[i] == 4)
start_view++;
for (i=0;i<path_guess.length;i++) {
if (state->common->paths[counter].p[p] ==
state->common->paths[counter].mapping[i]) {
- if (path_guess.guess[i] == 1 && mirror == true)
+ if (path_guess.guess[i] == 1 && mirror)
end_view++;
- if (path_guess.guess[i] == 2 && mirror == false)
+ if (path_guess.guess[i] == 2 && !mirror)
end_view++;
if (path_guess.guess[i] == 4)
end_view++;
return cNone;
}
-int check_numbers(game_state *state, int *guess) {
- int valid;
+bool check_numbers(game_state *state, int *guess) {
+ bool valid;
int i;
int count_ghosts, count_vampires, count_zombies;
return valid;
}
-int check_solution(int *g, struct path path) {
+bool check_solution(int *g, struct path path) {
int i;
- int mirror;
+ bool mirror;
int count;
count = 0;
return true;
}
-int solve_iterative(game_state *state, struct path *paths) {
- int solved;
+bool solve_iterative(game_state *state, struct path *paths) {
+ bool solved;
int p,i,j,count;
int *guess;
return solved;
}
-int solve_bruteforce(game_state *state, struct path *paths) {
- int solved, correct;
+bool solve_bruteforce(game_state *state, struct path *paths) {
+ bool solved, correct;
int number_solutions;
int p,i;
int filling;
int max_length;
int count_ghosts, count_vampires, count_zombies;
- int abort;
+ bool abort;
float ratio;
/* Variables for solver algorithm */
- int solved_iterative, solved_bruteforce, contains_inconsistency,
- count_ambiguous;
+ bool solved_iterative, solved_bruteforce, contains_inconsistency;
+ int count_ambiguous;
int iterative_depth;
int *old_guess;
/* Initialize fixed flag from common. Not needed for the
* puzzle generator; initialize it for having clean code */
- new->common->fixed = snewn(new->common->num_total,int);
+ new->common->fixed = snewn(new->common->num_total, bool);
for (g=0;g<new->common->num_total;g++)
new->common->fixed[g] = false;
/* Prepare path information needed by the solver (containing all hints) */
for (p=0;p<new->common->num_paths;p++) {
- int mirror,x,y;
+ bool mirror;
+ int x,y;
new->common->paths[p].sightings_start = 0;
new->common->paths[p].sightings_end = 0;
if (new->common->paths[p].p[g] == -1) mirror = true;
else {
- if (new->guess[new->common->paths[p].p[g]] == 1 && mirror == true) (new->common->paths[p].sightings_start)++;
- else if (new->guess[new->common->paths[p].p[g]] == 2 && mirror == false) (new->common->paths[p].sightings_start)++;
+ if (new->guess[new->common->paths[p].p[g]] == 1 && mirror) (new->common->paths[p].sightings_start)++;
+ else if (new->guess[new->common->paths[p].p[g]] == 2 && !mirror) (new->common->paths[p].sightings_start)++;
else if (new->guess[new->common->paths[p].p[g]] == 4) (new->common->paths[p].sightings_start)++;
}
}
for (g=new->common->paths[p].length-1;g>=0;g--) {
if (new->common->paths[p].p[g] == -1) mirror = true;
else {
- if (new->guess[new->common->paths[p].p[g]] == 1 && mirror == true) (new->common->paths[p].sightings_end)++;
- else if (new->guess[new->common->paths[p].p[g]] == 2 && mirror == false) (new->common->paths[p].sightings_end)++;
+ if (new->guess[new->common->paths[p].p[g]] == 1 && mirror) (new->common->paths[p].sightings_end)++;
+ else if (new->guess[new->common->paths[p].p[g]] == 2 && !mirror) (new->common->paths[p].sightings_end)++;
else if (new->guess[new->common->paths[p].p[g]] == 4) (new->common->paths[p].sightings_end)++;
}
}
count_ambiguous = 0;
while (true) {
- int no_change;
- no_change = true;
+ bool no_change = true;
solved_iterative = solve_iterative(new,new->common->paths);
iterative_depth++;
for (p=0;p<new->common->num_total;p++) {
state->guess = snewn(state->common->num_total,int);
state->pencils = snewn(state->common->num_total,unsigned char);
- state->common->fixed = snewn(state->common->num_total,int);
+ state->common->fixed = snewn(state->common->num_total, bool);
for (i=0;i<state->common->num_total;i++) {
state->guess[i] = 7;
state->pencils[i] = 0;
int p;
int *old_guess;
int iterative_depth;
- int solved_iterative, solved_bruteforce, contains_inconsistency,
- count_ambiguous;
+ bool solved_iterative, solved_bruteforce, contains_inconsistency;
+ int count_ambiguous;
int i;
char *move, *c;
/* Try to solve the puzzle with the iterative solver */
while (true) {
- int no_change;
- no_change = true;
+ bool no_change = true;
solved_iterative =
solve_iterative(solve_state,solve_state->common->paths);
iterative_depth++;
struct game_ui {
int hx, hy; /* as for solo.c, highlight pos */
- int hshow, hpencil, hcursor; /* show state, type, and ?cursor. */
- int ascii;
+ bool hshow, hpencil, hcursor; /* show state, type, and ?cursor. */
+ bool ascii;
};
static game_ui *new_ui(const game_state *state)
{
game_ui *ui = snew(game_ui);
ui->hx = ui->hy = 0;
- ui->hpencil = ui->hshow = ui->hcursor = 0;
+ ui->hpencil = false;
+ ui->hshow = false;
+ ui->hcursor = false;
ui->ascii = false;
return ui;
}
if (ui->hshow && ui->hpencil && !ui->hcursor) {
int g = newstate->guess[newstate->common->xinfo[ui->hx + ui->hy*(newstate->common->params.w+2)]];
if (g == 1 || g == 2 || g == 4)
- ui->hshow = 0;
+ ui->hshow = false;
}
}
struct game_drawstate {
- int tilesize, started, solved;
+ int tilesize;
+ bool started, solved;
int w, h;
int *monsters;
unsigned char *pencils;
- unsigned char count_errors[3];
- unsigned char *cell_errors;
- unsigned char *hint_errors;
- unsigned char *hints_done;
+ bool count_errors[3];
+ bool *cell_errors;
+ bool *hint_errors;
+ bool *hints_done;
- int hx, hy, hshow, hpencil; /* as for game_ui. */
- int hflash;
- int ascii;
+ int hx, hy;
+ bool hshow, hpencil; /* as for game_ui. */
+ bool hflash;
+ bool ascii;
};
-static int is_clue(const game_state *state, int x, int y)
+static bool is_clue(const game_state *state, int x, int y)
{
int h = state->common->params.h, w = state->common->params.w;
return dupstr("M");
}
- if (ui->hshow == 1 && ui->hpencil == 0) {
+ if (ui->hshow && !ui->hpencil) {
xi = state->common->xinfo[ui->hx + ui->hy*(state->common->params.w+2)];
if (xi >= 0 && !state->common->fixed[xi]) {
if (button == 'g' || button == 'G' || button == '1') {
- if (!ui->hcursor) ui->hshow = 0;
+ if (!ui->hcursor) ui->hshow = false;
sprintf(buf,"G%d",xi);
return dupstr(buf);
}
if (button == 'v' || button == 'V' || button == '2') {
- if (!ui->hcursor) ui->hshow = 0;
+ if (!ui->hcursor) ui->hshow = false;
sprintf(buf,"V%d",xi);
return dupstr(buf);
}
if (button == 'z' || button == 'Z' || button == '3') {
- if (!ui->hcursor) ui->hshow = 0;
+ if (!ui->hcursor) ui->hshow = false;
sprintf(buf,"Z%d",xi);
return dupstr(buf);
}
if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 ||
button == '0' || button == '\b' ) {
- if (!ui->hcursor) ui->hshow = 0;
+ if (!ui->hcursor) ui->hshow = false;
sprintf(buf,"E%d",xi);
return dupstr(buf);
}
case CURSOR_RIGHT: ui->hx += (ui->hx < ds->w) ? 1 : 0; break;
case CURSOR_LEFT: ui->hx -= (ui->hx > 1) ? 1 : 0; break;
}
- ui->hshow = ui->hcursor = 1;
+ ui->hshow = true;
+ ui->hcursor = true;
return UI_UPDATE;
}
if (ui->hshow && button == CURSOR_SELECT) {
- ui->hpencil = 1 - ui->hpencil;
- ui->hcursor = 1;
+ ui->hpencil = !ui->hpencil;
+ ui->hcursor = true;
return UI_UPDATE;
}
- if (ui->hshow == 1 && ui->hpencil == 1) {
+ if (ui->hshow && ui->hpencil) {
xi = state->common->xinfo[ui->hx + ui->hy*(state->common->params.w+2)];
if (xi >= 0 && !state->common->fixed[xi]) {
if (button == 'g' || button == 'G' || button == '1') {
sprintf(buf,"g%d",xi);
- if (!ui->hcursor) ui->hpencil = ui->hshow = 0;
+ if (!ui->hcursor) {
+ ui->hpencil = false;
+ ui->hshow = false;
+ }
return dupstr(buf);
}
if (button == 'v' || button == 'V' || button == '2') {
sprintf(buf,"v%d",xi);
- if (!ui->hcursor) ui->hpencil = ui->hshow = 0;
+ if (!ui->hcursor) {
+ ui->hpencil = false;
+ ui->hshow = false;
+ }
return dupstr(buf);
}
if (button == 'z' || button == 'Z' || button == '3') {
sprintf(buf,"z%d",xi);
- if (!ui->hcursor) ui->hpencil = ui->hshow = 0;
+ if (!ui->hcursor) {
+ ui->hpencil = false;
+ ui->hshow = false;
+ }
return dupstr(buf);
}
if (button == 'e' || button == 'E' || button == CURSOR_SELECT2 ||
button == '0' || button == '\b') {
sprintf(buf,"E%d",xi);
- if (!ui->hcursor) ui->hpencil = ui->hshow = 0;
+ if (!ui->hcursor) {
+ ui->hpencil = false;
+ ui->hshow = false;
+ }
return dupstr(buf);
}
}
xi = state->common->xinfo[gx+gy*(state->common->params.w+2)];
if (xi >= 0 && !state->common->fixed[xi]) {
g = state->guess[xi];
- if (ui->hshow == 0) {
+ if (!ui->hshow) {
if (button == LEFT_BUTTON) {
- ui->hshow = 1; ui->hpencil = 0; ui->hcursor = 0;
+ ui->hshow = true;
+ ui->hpencil = false;
+ ui->hcursor = false;
ui->hx = gx; ui->hy = gy;
return UI_UPDATE;
}
else if (button == RIGHT_BUTTON && g == 7) {
- ui->hshow = 1; ui->hpencil = 1; ui->hcursor = 0;
+ ui->hshow = true;
+ ui->hpencil = true;
+ ui->hcursor = false;
ui->hx = gx; ui->hy = gy;
return UI_UPDATE;
}
}
- else if (ui->hshow == 1) {
+ else if (ui->hshow) {
if (button == LEFT_BUTTON) {
- if (ui->hpencil == 0) {
+ if (!ui->hpencil) {
if (gx == ui->hx && gy == ui->hy) {
- ui->hshow = 0; ui->hpencil = 0; ui->hcursor = 0;
+ ui->hshow = false;
+ ui->hpencil = false;
+ ui->hcursor = false;
ui->hx = 0; ui->hy = 0;
return UI_UPDATE;
}
else {
- ui->hshow = 1; ui->hpencil = 0; ui->hcursor = 0;
+ ui->hshow = true;
+ ui->hpencil = false;
+ ui->hcursor = false;
ui->hx = gx; ui->hy = gy;
return UI_UPDATE;
}
}
else {
- ui->hshow = 1; ui->hpencil = 0; ui->hcursor = 0;
+ ui->hshow = true;
+ ui->hpencil = false;
+ ui->hcursor = false;
ui->hx = gx; ui->hy = gy;
return UI_UPDATE;
}
}
else if (button == RIGHT_BUTTON) {
- if (ui->hpencil == 0 && g == 7) {
- ui->hshow = 1; ui->hpencil = 1; ui->hcursor = 0;
+ if (!ui->hpencil && g == 7) {
+ ui->hshow = true;
+ ui->hpencil = true;
+ ui->hcursor = false;
ui->hx = gx; ui->hy = gy;
return UI_UPDATE;
}
else {
if (gx == ui->hx && gy == ui->hy) {
- ui->hshow = 0; ui->hpencil = 0; ui->hcursor = 0;
+ ui->hshow = false;
+ ui->hpencil = false;
+ ui->hcursor = false;
ui->hx = 0; ui->hy = 0;
return UI_UPDATE;
}
else if (g == 7) {
- ui->hshow = 1; ui->hpencil = 1; ui->hcursor = 0;
+ ui->hshow = true;
+ ui->hpencil = true;
+ ui->hcursor = false;
ui->hx = gx; ui->hy = gy;
return UI_UPDATE;
}
return NULL;
}
-int check_numbers_draw(game_state *state, int *guess) {
- int valid, filled;
+bool check_numbers_draw(game_state *state, int *guess) {
+ bool valid, filled;
int i,x,y,xy;
int count_ghosts, count_vampires, count_zombies;
return valid;
}
-int check_path_solution(game_state *state, int p) {
+bool check_path_solution(game_state *state, int p) {
int i;
- int mirror;
+ bool mirror;
int count;
- int correct;
+ bool correct;
int unfilled;
count = 0;
{
int x,y,n,p,i;
char c;
- int correct;
- int solver;
+ bool correct;
+ bool solver;
game_state *ret = dup_game(state);
solver = false;
for (i=0;i<state->common->num_total;i++)
ds->pencils[i] = 0;
- ds->cell_errors = snewn(state->common->wh,unsigned char);
+ ds->cell_errors = snewn(state->common->wh,bool);
for (i=0;i<state->common->wh;i++)
ds->cell_errors[i] = false;
- ds->hint_errors = snewn(2*state->common->num_paths,unsigned char);
+ ds->hint_errors = snewn(2*state->common->num_paths,bool);
for (i=0;i<2*state->common->num_paths;i++)
ds->hint_errors[i] = false;
- ds->hints_done = snewn(2 * state->common->num_paths, unsigned char);
+ ds->hints_done = snewn(2 * state->common->num_paths, bool);
memset(ds->hints_done, 0,
- 2 * state->common->num_paths * sizeof(unsigned char));
+ 2 * state->common->num_paths * sizeof(bool));
- ds->hshow = ds->hpencil = ds->hflash = 0;
+ ds->hshow = false;
+ ds->hpencil = false;
+ ds->hflash = false;
ds->hx = ds->hy = 0;
return ds;
}
const game_state *state, const game_ui *ui,
int x, int y) {
- int hon;
+ bool hon;
int dx,dy;
dx = BORDER+(x* ds->tilesize)+(TILESIZE/2);
dy = BORDER+(y* ds->tilesize)+(TILESIZE/2)+TILESIZE;
}
static void draw_monster(drawing *dr, game_drawstate *ds, int x, int y,
- int tilesize, int hflash, int monster)
+ int tilesize, bool hflash, int monster)
{
int black = (hflash ? COL_FLASH : COL_TEXT);
}
static void draw_monster_count(drawing *dr, game_drawstate *ds,
- const game_state *state, int c, int hflash) {
+ const game_state *state, int c, bool hflash) {
int dx,dy;
char buf[8];
char bufm[8];
static void draw_path_hint(drawing *dr, game_drawstate *ds,
const struct game_params *params,
- int hint_index, int hflash, int hint) {
+ int hint_index, bool hflash, int hint) {
int x, y, color, dx, dy, text_dx, text_dy, text_size;
char buf[4];
static void draw_mirror(drawing *dr, game_drawstate *ds,
const game_state *state, int x, int y,
- int hflash, int mirror) {
+ bool hflash, int mirror) {
int dx,dy,mx1,my1,mx2,my2;
dx = BORDER+(x* ds->tilesize)+(TILESIZE/2);
dy = BORDER+(y* ds->tilesize)+(TILESIZE/2)+TILESIZE;
static void draw_big_monster(drawing *dr, game_drawstate *ds,
const game_state *state, int x, int y,
- int hflash, int monster)
+ bool hflash, int monster)
{
int dx,dy;
char buf[10];
if (!ds->ascii) {
draw_monster(dr, ds,
dx + TILESIZE/2 * px, dy + TILESIZE/2 * py,
- TILESIZE/2, 0, monsters[py*2+px]);
+ TILESIZE/2, false, monsters[py*2+px]);
}
else {
switch (monsters[py*2+px]) {
#define FLASH_TIME 0.7F
-static int is_hint_stale(const game_drawstate *ds, int hflash,
- const game_state *state, int index)
+static bool is_hint_stale(const game_drawstate *ds, bool hflash,
+ const game_state *state, int index)
{
- int ret = false;
+ bool ret = false;
if (!ds->started) ret = true;
if (ds->hflash != hflash) ret = true;
float animtime, float flashtime)
{
int i,j,x,y,xy;
- int stale, xi, c, hflash, hchanged, changed_ascii;
+ int xi, c;
+ bool stale, hflash, hchanged, changed_ascii;
hflash = (int)(flashtime * 5 / FLASH_TIME) % 2;
NCOLOURS
};
+typedef enum {
+ MODE_UNEQUAL, /* Puzzle indicators are 'greater-than'. */
+ MODE_ADJACENT /* Puzzle indicators are 'adjacent number'. */
+} Mode;
+
struct game_params {
int order; /* Size of latin square */
int diff; /* Difficulty */
- int adjacent; /* Puzzle indicators are 'adjacent number'
- not 'greater-than'. */
+ Mode mode;
};
#define F_IMMUTABLE 1 /* passed in as game description */
#define F_ERROR_MASK (F_ERROR|F_ERROR_UP|F_ERROR_RIGHT|F_ERROR_DOWN|F_ERROR_LEFT)
struct game_state {
- int order, completed, cheated, adjacent;
+ int order;
+ bool completed, cheated;
+ Mode mode;
digit *nums; /* actual numbers (size order^2) */
unsigned char *hints; /* remaining possiblities (size order^3) */
unsigned int *flags; /* flags (size order^2) */
*ret = unequal_presets[i]; /* structure copy */
sprintf(buf, "%s: %dx%d %s",
- ret->adjacent ? "Adjacent" : "Unequal",
+ ret->mode == MODE_ADJACENT ? "Adjacent" : "Unequal",
ret->order, ret->order,
unequal_diffnames[ret->diff]);
if (*p == 'a') {
p++;
- ret->adjacent = 1;
+ ret->mode = MODE_ADJACENT;
} else
- ret->adjacent = 0;
+ ret->mode = MODE_UNEQUAL;
if (*p == 'd') {
int i;
char ret[80];
sprintf(ret, "%d", params->order);
- if (params->adjacent)
+ if (params->mode == MODE_ADJACENT)
sprintf(ret + strlen(ret), "a");
if (full)
sprintf(ret + strlen(ret), "d%c", unequal_diffchars[params->diff]);
ret[0].name = "Mode";
ret[0].type = C_CHOICES;
ret[0].u.choices.choicenames = ":Unequal:Adjacent";
- ret[0].u.choices.selected = params->adjacent;
+ ret[0].u.choices.selected = params->mode;
ret[1].name = "Size (s*s)";
ret[1].type = C_STRING;
{
game_params *ret = snew(game_params);
- ret->adjacent = cfg[0].u.choices.selected;
+ ret->mode = cfg[0].u.choices.selected;
ret->order = atoi(cfg[1].u.string.sval);
ret->diff = cfg[2].u.choices.selected;
return "Order must be between 3 and 32";
if (params->diff >= DIFFCOUNT)
return "Unknown difficulty rating";
- if (params->order < 5 && params->adjacent &&
+ if (params->order < 5 && params->mode == MODE_ADJACENT &&
params->diff >= DIFF_SET)
return "Order must be at least 5 for Adjacent puzzles of this difficulty.";
return NULL;
{ F_ADJ_LEFT, F_ADJ_RIGHT, F_ERROR_LEFT, -1, 0, '<', '|' }
};
-static game_state *blank_game(int order, int adjacent)
+static game_state *blank_game(int order, Mode mode)
{
game_state *state = snew(game_state);
int o2 = order*order, o3 = o2*order;
state->order = order;
- state->adjacent = adjacent;
- state->completed = state->cheated = 0;
+ state->mode = mode;
+ state->completed = false;
+ state->cheated = false;
state->nums = snewn(o2, digit);
state->hints = snewn(o3, unsigned char);
static game_state *dup_game(const game_state *state)
{
- game_state *ret = blank_game(state->order, state->adjacent);
+ game_state *ret = blank_game(state->order, state->mode);
int o2 = state->order*state->order, o3 = o2*state->order;
memcpy(ret->nums, state->nums, o2 * sizeof(digit));
#define CHECKG(x,y) grid[(y)*o+(x)]
-/* Returns 0 if it finds an error, 1 otherwise. */
-static int check_num_adj(digit *grid, game_state *state,
- int x, int y, int me)
+/* Returns false if it finds an error, true if ok. */
+static bool check_num_adj(digit *grid, game_state *state,
+ int x, int y, bool me)
{
unsigned int f = GRID(state, flags, x, y);
- int ret = 1, i, o = state->order;
+ bool ret = true;
+ int i, o = state->order;
for (i = 0; i < 4; i++) {
int dx = adjthan[i].dx, dy = adjthan[i].dy, n, dn;
assert (n != 0);
if (dn == 0) continue;
- if (state->adjacent) {
+ if (state->mode == MODE_ADJACENT) {
int gd = abs(n-dn);
if ((f & adjthan[i].f) && (gd != 1)) {
debug(("check_adj error (%d,%d):%d should be | (%d,%d):%d",
x, y, n, x+dx, y+dy, dn));
if (me) GRID(state, flags, x, y) |= adjthan[i].fe;
- ret = 0;
+ ret = false;
}
if (!(f & adjthan[i].f) && (gd == 1)) {
debug(("check_adj error (%d,%d):%d should not be | (%d,%d):%d",
x, y, n, x+dx, y+dy, dn));
if (me) GRID(state, flags, x, y) |= adjthan[i].fe;
- ret = 0;
+ ret = false;
}
} else {
debug(("check_adj error (%d,%d):%d not > (%d,%d):%d",
x, y, n, x+dx, y+dy, dn));
if (me) GRID(state, flags, x, y) |= adjthan[i].fe;
- ret = 0;
+ ret = false;
}
}
}
return ret;
}
-/* Returns 0 if it finds an error, 1 otherwise. */
-static int check_num_error(digit *grid, game_state *state,
- int x, int y, int mark_errors)
+/* Returns false if it finds an error, true if ok. */
+static bool check_num_error(digit *grid, game_state *state,
+ int x, int y, bool mark_errors)
{
int o = state->order;
- int xx, yy, val = CHECKG(x,y), ret = 1;
+ int xx, yy, val = CHECKG(x,y);
+ bool ret = true;
assert(val != 0);
/* check for dups in same column. */
for (yy = 0; yy < state->order; yy++) {
if (yy == y) continue;
- if (CHECKG(x,yy) == val) ret = 0;
+ if (CHECKG(x,yy) == val) ret = false;
}
/* check for dups in same row. */
for (xx = 0; xx < state->order; xx++) {
if (xx == x) continue;
- if (CHECKG(xx,y) == val) ret = 0;
+ if (CHECKG(xx,y) == val) ret = false;
}
if (!ret) {
* 0 for 'incomplete'
* 1 for 'complete and correct'
*/
-static int check_complete(digit *grid, game_state *state, int mark_errors)
+static int check_complete(digit *grid, game_state *state, bool mark_errors)
{
int x, y, ret = 1, o = state->order;
*p++ = n > 0 ? n2c(n, state->order) : '.';
if (x < (state->order-1)) {
- if (state->adjacent) {
+ if (state->mode == MODE_ADJACENT) {
*p++ = (GRID(state, flags, x, y) & F_ADJ_RIGHT) ? '|' : ' ';
} else {
if (GRID(state, flags, x, y) & F_ADJ_RIGHT)
if (y < (state->order-1)) {
for (x = 0; x < state->order; x++) {
- if (state->adjacent) {
+ if (state->mode == MODE_ADJACENT) {
*p++ = (GRID(state, flags, x, y) & F_ADJ_DOWN) ? '-' : ' ';
} else {
if (GRID(state, flags, x, y) & F_ADJ_DOWN)
ctx->links = NULL;
ctx->state = state;
- if (state->adjacent) return ctx; /* adjacent mode doesn't use links. */
+ if (state->mode == MODE_ADJACENT)
+ return ctx; /* adjacent mode doesn't use links. */
for (x = 0; x < o; x++) {
for (y = 0; y < o; y++) {
* adjacent possibles reflect the adjacent/non-adjacent clue. */
for (i = 0; i < 4; i++) {
- int isadjacent = (GRID(ctx->state, flags, x, y) & adjthan[i].f);
+ bool isadjacent =
+ (GRID(ctx->state, flags, x, y) & adjthan[i].f);
nx = x + adjthan[i].dx, ny = y + adjthan[i].dy;
if (nx < 0 || ny < 0 || nx >= o || ny >= o)
if (isadjacent && (gd == 1)) continue;
if (!isadjacent && (gd != 1)) continue;
- if (cube(nx, ny, n+1) == false)
+ if (!cube(nx, ny, n+1))
continue; /* already discounted this possibility. */
#ifdef STANDALONE_SOLVER
for (x = 0; x < o; x++) {
for (y = 0; y < o; y++) {
for (i = 0; i < 4; i++) {
- int isadjacent = (GRID(ctx->state, flags, x, y) & adjthan[i].f);
+ bool isadjacent =
+ (GRID(ctx->state, flags, x, y) & adjthan[i].f);
nx = x + adjthan[i].dx, ny = y + adjthan[i].dy;
if (nx < 0 || ny < 0 || nx >= o || ny >= o)
memset(scratch, 0, o*sizeof(int));
for (n = 0; n < o; n++) {
- if (cube(x, y, n+1) == false) continue;
+ if (!cube(x, y, n+1)) continue;
for (nn = 0; nn < o; nn++) {
if (n == nn) continue;
* currently set but are not indicated in scratch. */
for (n = 0; n < o; n++) {
if (scratch[n] == 1) continue;
- if (cube(nx, ny, n+1) == false) continue;
+ if (!cube(nx, ny, n+1)) continue;
#ifdef STANDALONE_SOLVER
if (solver_show_working) {
static int solver_easy(struct latin_solver *solver, void *vctx)
{
struct solver_ctx *ctx = (struct solver_ctx *)vctx;
- if (ctx->state->adjacent)
+ if (ctx->state->mode == MODE_ADJACENT)
return solver_adjacent(solver, vctx);
else
return solver_links(solver, vctx);
static int solver_set(struct latin_solver *solver, void *vctx)
{
struct solver_ctx *ctx = (struct solver_ctx *)vctx;
- if (ctx->state->adjacent)
+ if (ctx->state->mode == MODE_ADJACENT)
return solver_adjacent_set(solver, vctx);
else
return 0;
return soln;
}
-/* returns non-zero if it placed (or could have placed) clue. */
-static int gg_place_clue(game_state *state, int ccode, digit *latin, int checkonly)
+/* returns true if it placed (or could have placed) clue. */
+static bool gg_place_clue(game_state *state, int ccode, digit *latin, bool checkonly)
{
int loc = ccode / 5, which = ccode % 5;
int x = loc % state->order, y = loc / state->order;
}
#endif
assert(state->nums[loc] == latin[loc]);
- return 0;
+ return false;
}
if (!checkonly) {
state->nums[loc] = latin[loc];
} else { /* add flag */
int lx, ly, lloc;
- if (state->adjacent)
- return 0; /* never add flag clues in adjacent mode (they're always
- all present) */
+ if (state->mode == MODE_ADJACENT)
+ return false; /* never add flag clues in adjacent mode
+ (they're always all present) */
if (state->flags[loc] & adjthan[which].f)
- return 0; /* already has flag. */
+ return false; /* already has flag. */
lx = x + adjthan[which].dx;
ly = y + adjthan[which].dy;
if (lx < 0 || ly < 0 || lx >= state->order || ly >= state->order)
- return 0; /* flag compares to off grid */
+ return false; /* flag compares to off grid */
lloc = loc + adjthan[which].dx + adjthan[which].dy*state->order;
if (latin[loc] <= latin[lloc])
- return 0; /* flag would be incorrect */
+ return false; /* flag would be incorrect */
if (!checkonly) {
state->flags[loc] |= adjthan[which].f;
}
}
- return 1;
+ return true;
}
-/* returns non-zero if it removed (or could have removed) the clue. */
-static int gg_remove_clue(game_state *state, int ccode, int checkonly)
+/* returns true if it removed (or could have removed) the clue. */
+static bool gg_remove_clue(game_state *state, int ccode, bool checkonly)
{
int loc = ccode / 5, which = ccode % 5;
#ifdef STANDALONE_SOLVER
assert(loc < state->order*state->order);
if (which == 4) { /* remove number. */
- if (state->nums[loc] == 0) return 0;
+ if (state->nums[loc] == 0) return false;
if (!checkonly) {
#ifdef STANDALONE_SOLVER
if (solver_show_working)
state->nums[loc] = 0;
}
} else { /* remove flag */
- if (state->adjacent)
- return 0; /* never remove clues in adjacent mode. */
+ if (state->mode == MODE_ADJACENT)
+ return false; /* never remove clues in adjacent mode. */
- if (!(state->flags[loc] & adjthan[which].f)) return 0;
+ if (!(state->flags[loc] & adjthan[which].f)) return false;
if (!checkonly) {
#ifdef STANDALONE_SOLVER
if (solver_show_working)
state->flags[loc] &= ~adjthan[which].f;
}
}
- return 1;
+ return true;
}
static int gg_best_clue(game_state *state, int *scratch, digit *latin)
#endif
for (i = ls; i-- > 0 ;) {
- if (!gg_place_clue(state, scratch[i], latin, 1)) continue;
+ if (!gg_place_clue(state, scratch[i], latin, true)) continue;
loc = scratch[i] / 5;
for (j = nposs = 0; j < state->order; j++) {
if (solver_state(copy, difficulty) == 1) break;
best = gg_best_clue(copy, scratch, latin);
- gg_place_clue(new, scratch[best], latin, 0);
- gg_place_clue(copy, scratch[best], latin, 0);
+ gg_place_clue(new, scratch[best], latin, false);
+ gg_place_clue(copy, scratch[best], latin, false);
}
free_game(copy);
#ifdef STANDALONE_SOLVER
int difficulty)
{
int o = new->order, o2 = o*o, lscratch = o2*5, i;
- game_state *copy = blank_game(new->order, new->adjacent);
+ game_state *copy = blank_game(new->order, new->mode);
/* For each symbol (if it exists in new), try and remove it and
* solve again; if we couldn't solve without it put it back. */
for (i = 0; i < lscratch; i++) {
- if (!gg_remove_clue(new, scratch[i], 0)) continue;
+ if (!gg_remove_clue(new, scratch[i], false)) continue;
memcpy(copy->nums, new->nums, o2 * sizeof(digit));
memcpy(copy->flags, new->flags, o2 * sizeof(unsigned int));
gg_solved++;
if (solver_state(copy, difficulty) != 1) {
/* put clue back, we can't solve without it. */
- int ret = gg_place_clue(new, scratch[i], latin, 0);
- assert(ret == 1);
+ bool ret = gg_place_clue(new, scratch[i], latin, false);
+ assert(ret);
} else {
#ifdef STANDALONE_SOLVER
if (solver_show_working)
int o2 = params->order * params->order, ntries = 1;
int *scratch, lscratch = o2*5;
char *ret, buf[80];
- game_state *state = blank_game(params->order, params->adjacent);
+ game_state *state = blank_game(params->order, params->mode);
/* Generate a list of 'things to strip' (randomised later) */
scratch = snewn(lscratch, int);
memset(state->nums, 0, o2 * sizeof(digit));
memset(state->flags, 0, o2 * sizeof(unsigned int));
- if (state->adjacent) {
+ if (state->mode == MODE_ADJACENT) {
/* All adjacency flags are always present. */
add_adjacent_flags(state, sq);
}
static game_state *load_game(const game_params *params, const char *desc,
const char **why_r)
{
- game_state *state = blank_game(params->order, params->adjacent);
+ game_state *state = blank_game(params->order, params->mode);
const char *p = desc;
int i = 0, n, o = params->order, x, y;
const char *why = NULL;
if (nx < 0 || ny < 0 || nx >= o || ny >= o) {
why = "Flags go off grid"; goto fail;
}
- if (params->adjacent) {
+ if (params->mode == MODE_ADJACENT) {
/* if one cell is adjacent to another, the other must
* also be adjacent to the first. */
if (!(GRID(state, flags, nx, ny) & adjthan[n].fo)) {
struct game_ui {
int hx, hy; /* as for solo.c, highlight pos */
- int hshow, hpencil, hcursor; /* show state, type, and ?cursor. */
+ bool hshow, hpencil, hcursor; /* show state, type, and ?cursor. */
};
static game_ui *new_ui(const game_state *state)
game_ui *ui = snew(game_ui);
ui->hx = ui->hy = 0;
- ui->hpencil = ui->hshow = ui->hcursor = 0;
+ ui->hpencil = false;
+ ui->hshow = false;
+ ui->hcursor = false;
return ui;
}
* pencil mode. */
if (ui->hshow && ui->hpencil && !ui->hcursor &&
GRID(newstate, nums, ui->hx, ui->hy) != 0) {
- ui->hshow = 0;
+ ui->hshow = false;
}
}
struct game_drawstate {
- int tilesize, order, started, adjacent;
+ int tilesize, order;
+ bool started;
+ Mode mode;
digit *nums; /* copy of nums, o^2 */
unsigned char *hints; /* copy of hints, o^3 */
unsigned int *flags; /* o^2 */
- int hx, hy, hshow, hpencil; /* as for game_ui. */
- int hflash;
+ int hx, hy;
+ bool hshow, hpencil; /* as for game_ui. */
+ bool hflash;
};
static char *interpret_move(const game_state *state, game_ui *ui,
{
int x = FROMCOORD(ox), y = FROMCOORD(oy), n;
char buf[80];
- int shift_or_control = button & (MOD_SHFT | MOD_CTRL);
+ bool shift_or_control = button & (MOD_SHFT | MOD_CTRL);
button &= ~MOD_MASK;
if (button == LEFT_BUTTON) {
/* normal highlighting for non-immutable squares */
if (GRID(state, flags, x, y) & F_IMMUTABLE)
- ui->hshow = 0;
+ ui->hshow = false;
else if (x == ui->hx && y == ui->hy &&
- ui->hshow && ui->hpencil == 0)
- ui->hshow = 0;
+ ui->hshow && !ui->hpencil)
+ ui->hshow = false;
else {
- ui->hx = x; ui->hy = y; ui->hpencil = 0;
- ui->hshow = 1;
+ ui->hx = x; ui->hy = y; ui->hpencil = false;
+ ui->hshow = true;
}
- ui->hcursor = 0;
+ ui->hcursor = false;
return UI_UPDATE;
}
if (button == RIGHT_BUTTON) {
/* pencil highlighting for non-filled squares */
if (GRID(state, nums, x, y) != 0)
- ui->hshow = 0;
+ ui->hshow = false;
else if (x == ui->hx && y == ui->hy &&
ui->hshow && ui->hpencil)
- ui->hshow = 0;
+ ui->hshow = false;
else {
- ui->hx = x; ui->hy = y; ui->hpencil = 1;
- ui->hshow = 1;
+ ui->hx = x; ui->hy = y; ui->hpencil = true;
+ ui->hshow = true;
}
- ui->hcursor = 0;
+ ui->hcursor = false;
return UI_UPDATE;
}
}
if (IS_CURSOR_MOVE(button)) {
if (shift_or_control) {
- int nx = ui->hx, ny = ui->hy, i, self;
+ int nx = ui->hx, ny = ui->hy, i;
+ bool self;
move_cursor(button, &nx, &ny, ds->order, ds->order, false);
- ui->hshow = ui->hcursor = 1;
+ ui->hshow = true;
+ ui->hcursor = true;
for (i = 0; i < 4 && (nx != ui->hx + adjthan[i].dx ||
ny != ui->hy + adjthan[i].dy); ++i);
GRID(state, flags, nx, ny ) & adjthan[i].fo))
return UI_UPDATE; /* no clue to toggle */
- if (state->adjacent)
+ if (state->mode == MODE_ADJACENT)
self = (adjthan[i].dx >= 0 && adjthan[i].dy >= 0);
else
self = (GRID(state, flags, ui->hx, ui->hy) & adjthan[i].f);
return dupstr(buf);
} else {
move_cursor(button, &ui->hx, &ui->hy, ds->order, ds->order, false);
- ui->hshow = ui->hcursor = 1;
+ ui->hshow = true;
+ ui->hcursor = true;
return UI_UPDATE;
}
}
if (ui->hshow && IS_CURSOR_SELECT(button)) {
- ui->hpencil = 1 - ui->hpencil;
- ui->hcursor = 1;
+ ui->hpencil = !ui->hpencil;
+ ui->hcursor = true;
return UI_UPDATE;
}
sprintf(buf, "%c%d,%d,%d",
(char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n);
- if (!ui->hcursor) ui->hshow = 0;
+ if (!ui->hcursor) ui->hshow = false;
return dupstr(buf);
}
HINT(ret, x, y, i) = 0;
/* real change to grid; check for completion */
- if (!ret->completed && check_complete(ret->nums, ret, 1) > 0)
+ if (!ret->completed && check_complete(ret->nums, ret, true) > 0)
ret->completed = true;
}
return ret;
p++;
}
if (*p) goto badmove;
- rc = check_complete(ret->nums, ret, 1);
+ rc = check_complete(ret->nums, ret, true);
assert(rc > 0);
return ret;
} else if (move[0] == 'M') {
return ret;
} else if (move[0] == 'H') {
ret = solver_hint(state, NULL, DIFF_EASY, DIFF_EASY);
- check_complete(ret->nums, ret, 1);
+ check_complete(ret->nums, ret, true);
return ret;
} else if (move[0] == 'F' && sscanf(move+1, "%d,%d,%d", &x, &y, &n) == 3 &&
x >= 0 && x < state->order && y >= 0 && y < state->order) {
ds->tilesize = 0;
ds->order = state->order;
- ds->adjacent = state->adjacent;
+ ds->mode = state->mode;
ds->nums = snewn(o2, digit);
ds->hints = snewn(o3, unsigned char);
memset(ds->flags, 0, o2*sizeof(unsigned int));
ds->hx = ds->hy = 0;
- ds->started = ds->hshow = ds->hpencil = ds->hflash = 0;
+ ds->started = false;
+ ds->hshow = false;
+ ds->hpencil = false;
+ ds->hflash = false;
return ds;
}
static void draw_furniture(drawing *dr, game_drawstate *ds,
const game_state *state, const game_ui *ui,
- int x, int y, int hflash)
+ int x, int y, bool hflash)
{
- int ox = COORD(x), oy = COORD(y), bg, hon;
+ int ox = COORD(x), oy = COORD(y), bg;
+ bool hon;
unsigned int f = GRID(state, flags, x, y);
bg = hflash ? COL_HIGHLIGHT : COL_BACKGROUND;
draw_update(dr, ox, oy, TILE_SIZE, TILE_SIZE);
/* Draw the adjacent clue signs. */
- if (ds->adjacent)
+ if (ds->mode == MODE_ADJACENT)
draw_adjs(dr, ds, ox, oy, f, COL_BACKGROUND, COL_GRID);
else
draw_gts(dr, ds, ox, oy, f, COL_BACKGROUND, COL_TEXT);
int dir, const game_ui *ui,
float animtime, float flashtime)
{
- int x, y, i, hchanged = 0, stale, hflash = 0;
+ int x, y, i;
+ bool hchanged = false, stale, hflash = false;
debug(("highlight old (%d,%d), new (%d,%d)", ds->hx, ds->hy, ui->hx, ui->hy));
if (flashtime > 0 &&
(flashtime <= FLASH_TIME/3 || flashtime >= FLASH_TIME*2/3))
- hflash = 1;
+ hflash = true;
if (!ds->started) {
draw_rect(dr, 0, 0, DRAW_SIZE, DRAW_SIZE, COL_BACKGROUND);
}
if (ds->hx != ui->hx || ds->hy != ui->hy ||
ds->hshow != ui->hshow || ds->hpencil != ui->hpencil)
- hchanged = 1;
+ hchanged = true;
for (x = 0; x < ds->order; x++) {
for (y = 0; y < ds->order; y++) {
if (!ds->started)
- stale = 1;
+ stale = true;
else if (hflash != ds->hflash)
- stale = 1;
+ stale = true;
else
- stale = 0;
+ stale = false;
if (hchanged) {
if ((x == ui->hx && y == ui->hy) ||
(x == ds->hx && y == ds->hy))
- stale = 1;
+ stale = true;
}
if (GRID(state, nums, x, y) != GRID(ds, nums, x, y)) {
GRID(ds, nums, x, y) = GRID(state, nums, x, y);
- stale = 1;
+ stale = true;
}
if (GRID(state, flags, x, y) != GRID(ds, flags, x, y)) {
GRID(ds, flags, x, y) = GRID(state, flags, x, y);
- stale = 1;
+ stale = true;
}
if (GRID(ds, nums, x, y) == 0) {
/* We're not a number square (therefore we might
for (i = 0; i < ds->order; i++) {
if (HINT(state, x, y, i) != HINT(ds, x, y, i)) {
HINT(ds, x, y, i) = HINT(state, x, y, i);
- stale = 1;
+ stale = true;
}
}
}
ds->hshow = ui->hshow;
ds->hpencil = ui->hpencil;
- ds->started = 1;
+ ds->started = true;
ds->hflash = hflash;
}
FONT_VARIABLE, TILE_SIZE/2, ALIGN_VCENTRE | ALIGN_HCENTRE,
ink, str);
- if (state->adjacent)
+ if (state->mode == MODE_ADJACENT)
draw_adjs(dr, ds, ox, oy, GRID(state, flags, x, y), -1, ink);
else
draw_gts(dr, ds, ox, oy, GRID(state, flags, x, y), -1, ink);
static void check(game_params *p)
{
- const char *msg = validate_params(p, 1);
+ const char *msg = validate_params(p, true);
if (msg) {
fprintf(stderr, "%s: %s", quis, msg);
exit(1);
check(p);
solver_show_working = debug;
- desc = new_game_desc(p, rs, &aux, 0);
+ desc = new_game_desc(p, rs, &aux, false);
diff = solve(p, desc, debug);
sfree(aux);
sfree(desc);
tt_start = tt_now = time(NULL);
printf("Soak-generating an %s %dx%d grid, difficulty %s.\n",
- p->adjacent ? "adjacent" : "unequal",
+ p->mode == MODE_ADJACENT ? "adjacent" : "unequal",
p->order, p->order, unequal_diffnames[p->diff]);
while (1) {
p->diff = realdiff;
- desc = new_game_desc(p, rs, &aux, 0);
+ desc = new_game_desc(p, rs, &aux, false);
st = new_game(NULL, p, desc);
solver_state(st, DIFF_RECURSIVE);
free_game(st);
#define TOCHAR(c,id) (E_FROM_FRONT(c,id) + ('a'-1))
struct game_params {
- int w, diff, id;
+ int w, diff;
+ bool id;
};
struct game_state {
game_params par;
digit *grid;
- unsigned char *immutable;
+ bool *immutable;
int *pencil; /* bitmaps using bits 1<<1..1<<n */
- int completed, cheated;
+ bool completed, cheated;
digit *sequence; /* sequence of group elements shown */
/*
state->par = *params; /* structure copy */
state->grid = snewn(a, digit);
- state->immutable = snewn(a, unsigned char);
+ state->immutable = snewn(a, bool);
state->pencil = snewn(a, int);
for (i = 0; i < a; i++) {
state->grid[i] = 0;
- state->immutable[i] = 0;
+ state->immutable[i] = false;
state->pencil[i] = 0;
}
state->sequence = snewn(w, digit);
if (state->grid[i] != 0)
state->immutable[i] = true;
- state->completed = state->cheated = false;
+ state->completed = false;
+ state->cheated = false;
return state;
}
ret->par = state->par; /* structure copy */
ret->grid = snewn(a, digit);
- ret->immutable = snewn(a, unsigned char);
+ ret->immutable = snewn(a, bool);
ret->pencil = snewn(a, int);
ret->sequence = snewn(w, digit);
ret->dividers = snewn(w, int);
memcpy(ret->grid, state->grid, a*sizeof(digit));
- memcpy(ret->immutable, state->immutable, a*sizeof(unsigned char));
+ memcpy(ret->immutable, state->immutable, a*sizeof(bool));
memcpy(ret->pencil, state->pencil, a*sizeof(int));
memcpy(ret->sequence, state->sequence, w*sizeof(digit));
memcpy(ret->dividers, state->dividers, w*sizeof(int));
* This indicates whether the current highlight is a
* pencil-mark one or a real one.
*/
- int hpencil;
+ bool hpencil;
/*
* This indicates whether or not we're showing the highlight
* (used to be hx = hy = -1); important so that when we're
* fixed position. When hshow = 1, pressing a valid number
* or letter key or Space will enter that number or letter in the grid.
*/
- int hshow;
+ bool hshow;
/*
* This indicates whether we're using the highlight as a cursor;
* it means that it doesn't vanish on a keypress, and that it is
* allowed on immutable squares.
*/
- int hcursor;
+ bool hcursor;
/*
* This indicates whether we're dragging a table header to
* reposition an entire row or column.
game_ui *ui = snew(game_ui);
ui->hx = ui->hy = 0;
- ui->hpencil = ui->hshow = ui->hcursor = 0;
+ ui->hpencil = false;
+ ui->hshow = false;
+ ui->hcursor = false;
ui->drag = 0;
return ui;
*/
if (ui->hshow && ui->hpencil && !ui->hcursor &&
newstate->grid[ui->hy * w + ui->hx] != 0) {
- ui->hshow = 0;
+ ui->hshow = false;
}
if (ui->hshow && ui->odn > 1) {
/*
for (i = 0; i < ui->odn; i++) {
if (oldstate->sequence[ui->ohx + i*ui->odx] !=
newstate->sequence[ui->ohx + i*ui->odx]) {
- ui->hshow = 0;
+ ui->hshow = false;
break;
}
if (oldstate->sequence[ui->ohy + i*ui->ody] !=
newstate->sequence[ui->ohy + i*ui->ody]) {
- ui->hshow = 0;
+ ui->hshow = false;
break;
}
}
struct game_drawstate {
game_params par;
int w, tilesize;
- int started;
+ bool started;
long *tiles, *legend, *pencil, *errors;
long *errtmp;
digit *sequence;
};
-static int check_errors(const game_state *state, long *errors)
+static bool check_errors(const game_state *state, long *errors)
{
int w = state->par.w, a = w*w;
digit *grid = state->grid;
- int i, j, k, x, y, errs = false;
+ int i, j, k, x, y;
+ bool errs = false;
/*
* To verify that we have a valid group table, it suffices to
ty = state->sequence[ty];
if (button == LEFT_BUTTON) {
if (tx == ui->hx && ty == ui->hy &&
- ui->hshow && ui->hpencil == 0) {
- ui->hshow = 0;
+ ui->hshow && !ui->hpencil) {
+ ui->hshow = false;
} else {
ui->hx = tx;
ui->hy = ty;
ui->odx = ui->ody = 0;
ui->odn = 1;
ui->hshow = !state->immutable[ty*w+tx];
- ui->hpencil = 0;
+ ui->hpencil = false;
}
- ui->hcursor = 0;
+ ui->hcursor = false;
return UI_UPDATE;
}
if (button == RIGHT_BUTTON) {
if (state->grid[ty*w+tx] == 0) {
if (tx == ui->hx && ty == ui->hy &&
ui->hshow && ui->hpencil) {
- ui->hshow = 0;
+ ui->hshow = false;
} else {
- ui->hpencil = 1;
+ ui->hpencil = true;
ui->hx = tx;
ui->hy = ty;
ui->ohx = otx;
ui->ohy = oty;
ui->odx = ui->ody = 0;
ui->odn = 1;
- ui->hshow = 1;
+ ui->hshow = true;
}
} else {
- ui->hshow = 0;
+ ui->hshow = false;
}
- ui->hcursor = 0;
+ ui->hcursor = false;
return UI_UPDATE;
}
} else if (tx >= 0 && tx < w && ty == -1) {
if (IS_CURSOR_MOVE(button)) {
int cx = find_in_sequence(state->sequence, w, ui->hx);
int cy = find_in_sequence(state->sequence, w, ui->hy);
- move_cursor(button, &cx, &cy, w, w, 0);
+ move_cursor(button, &cx, &cy, w, w, false);
ui->hx = state->sequence[cx];
ui->hy = state->sequence[cy];
- ui->hshow = ui->hcursor = 1;
+ ui->hshow = true;
+ ui->hcursor = true;
return UI_UPDATE;
}
if (ui->hshow &&
(button == CURSOR_SELECT)) {
- ui->hpencil = 1 - ui->hpencil;
- ui->hcursor = 1;
+ ui->hpencil = !ui->hpencil;
+ ui->hcursor = true;
return UI_UPDATE;
}
}
movebuf = sresize(movebuf, buflen+1, char);
- if (!ui->hcursor) ui->hshow = 0;
+ if (!ui->hcursor) ui->hshow = false;
return movebuf;
}
sscanf(move+1, "%d,%d,%d%n", &x, &y, &n, &pos) == 3 &&
n >= 0 && n <= w) {
const char *mp = move + 1 + pos;
- int pencil = (move[0] == 'P');
+ bool pencil = (move[0] == 'P');
ret = dup_game(from);
while (1) {
tile |= DF_HIGHLIGHT;
} else if (ui->hshow) {
int i = abs(x - ui->ohx);
- int highlight = 0;
+ bool highlight = false;
if (ui->odn > 1) {
/*
* When a diagonal multifill selection is shown,
if (i >= 0 && i < ui->odn &&
x == ui->ohx + i*ui->odx &&
y == ui->ohy + i*ui->ody)
- highlight = 1;
+ highlight = true;
} else {
/*
* For a single square, we move its highlight
char *id = NULL, *desc;
const char *err;
digit *grid;
- int grade = false;
- int ret, diff, really_show_working = false;
+ bool grade = false;
+ int ret, diff;
+ bool really_show_working = false;
while (--argc > 0) {
char *p = *++argv;
* the puzzle internally before doing anything else.
*/
ret = -1; /* placate optimiser */
- solver_show_working = false;
+ solver_show_working = 0;
for (diff = 0; diff < DIFFCOUNT; diff++) {
memcpy(grid, s->grid, p->w * p->w);
ret = solver(&s->par, grid, diff);
* tracks whether or not the connected components containing
* yx1 and yx2 are known to be distinct.
*/
- unsigned char *disconnect;
+ bool *disconnect;
/*
* Temporary space used only inside particular solver loops.
sc->dsf = snew_dsf(wh);
sc->size = snewn(wh, int);
sc->contents = snewn(wh * k, int);
- sc->disconnect = snewn(wh*wh, unsigned char);
+ sc->disconnect = snewn(wh*wh, bool);
sc->tmp = snewn(wh, int);
return sc;
* Mark the components as disconnected from each other in the
* disconnect matrix.
*/
- sc->disconnect[yx1*wh+yx2] = sc->disconnect[yx2*wh+yx1] = 1;
+ sc->disconnect[yx1*wh+yx2] = true;
+ sc->disconnect[yx2*wh+yx1] = true;
}
void solver_init(struct solver_scratch *sc)
*/
dsf_init(sc->dsf, wh);
for (i = 0; i < wh; i++) sc->size[i] = 1;
- memset(sc->disconnect, 0, wh*wh);
+ memset(sc->disconnect, 0, wh*wh * sizeof(bool));
}
int solver_attempt(struct solver_scratch *sc, const unsigned char *grid,
- unsigned char *gen_lock)
+ bool *gen_lock)
{
int w = sc->w, h = sc->h, k = sc->k;
int wh = w*h;
int i, x, y;
- int done_something_overall = false;
+ bool done_something_overall = false;
/*
* Set up the contents array from the grid.
sc->contents[dsf_canonify(sc->dsf, i)*k+grid[i]] = i;
while (1) {
- int done_something = false;
+ bool done_something = false;
/*
* Go over the grid looking for reasons to add to the
* based deductions.
*/
if (gen_lock) {
- gen_lock[sc->contents[yx*k+i]] = 1;
- gen_lock[sc->contents[yx2*k+i]] = 1;
+ gen_lock[sc->contents[yx*k+i]] = true;
+ gen_lock[sc->contents[yx2*k+i]] = true;
}
}
}
unsigned char *shuffled;
int i, j, m, retries;
int *permutation;
- unsigned char *gen_lock;
+ bool *gen_lock;
extern int *divvy_rectangle(int w, int h, int k, random_state *rs);
sc = solver_scratch_new(w, h, k);
grid = snewn(wh, unsigned char);
shuffled = snewn(k, unsigned char);
permutation = snewn(wh, int);
- gen_lock = snewn(wh, unsigned char);
+ gen_lock = snewn(wh, bool);
do {
int *dsf = divvy_rectangle(w, h, k, rs);
* on for deductions. This is gradually updated by
* solver_attempt().
*/
- memset(gen_lock, 0, wh);
+ memset(gen_lock, 0, wh * sizeof(bool));
/*
* Now repeatedly fill the grid with letters, and attempt
struct game_immutable_state {
int refcount;
- unsigned char *forcefield;
+ bool *forcefield;
};
struct game_solution {
int lastmoved, lastmoved_pos; /* for move counting */
int movecount;
int completed;
- int cheated;
+ bool cheated;
struct game_immutable_state *imm;
struct game_solution *soln;
int soln_index;
}
static char *board_text_format(int w, int h, unsigned char *data,
- unsigned char *forcefield)
+ bool *forcefield)
{
int wh = w*h;
int *dsf = snew_dsf(wh);
* which is a pointer to a dynamically allocated array.
*/
static int solve_board(int w, int h, unsigned char *board,
- unsigned char *forcefield, int tx, int ty,
+ bool *forcefield, int tx, int ty,
int movelimit, int **moveout)
{
int wh = w*h;
struct board *b, *b2, *b3;
- int *next, *anchors, *which;
- int *movereached, *movequeue, mqhead, mqtail;
+ int *next, *which;
+ bool *anchors, *movereached;
+ int *movequeue, mqhead, mqtail;
tree234 *sorted, *queue;
int i, j, dir;
int qlen, lastdist;
qlen = 1;
next = snewn(wh, int);
- anchors = snewn(wh, int);
+ anchors = snewn(wh, bool);
which = snewn(wh, int);
- movereached = snewn(wh, int);
+ movereached = snewn(wh, bool);
movequeue = snewn(wh, int);
lastdist = -1;
static void generate_board(int w, int h, int *rtx, int *rty, int *minmoves,
random_state *rs, unsigned char **rboard,
- unsigned char **rforcefield, int movelimit)
+ bool **rforcefield, int movelimit)
{
int wh = w*h;
- unsigned char *board, *board2, *forcefield;
- unsigned char *tried_merge;
+ unsigned char *board, *board2;
+ bool *forcefield;
+ bool *tried_merge;
int *dsf;
int *list, nlist, pos;
int tx, ty;
* border of walls.
*/
board = snewn(wh, unsigned char);
- forcefield = snewn(wh, unsigned char);
+ forcefield = snewn(wh, bool);
board2 = snewn(wh, unsigned char);
memset(board, ANCHOR, wh);
- memset(forcefield, false, wh);
+ memset(forcefield, 0, wh * sizeof(bool));
for (i = 0; i < w; i++)
board[i] = board[i+w*(h-1)] = WALL;
for (i = 0; i < h; i++)
board[i*w] = board[i*w+(w-1)] = WALL;
- tried_merge = snewn(wh * wh, unsigned char);
- memset(tried_merge, 0, wh*wh);
+ tried_merge = snewn(wh * wh, bool);
+ memset(tried_merge, 0, wh*wh * sizeof(bool));
dsf = snew_dsf(wh);
/*
*/
tx = w-2;
ty = h-3;
- forcefield[ty*w+tx+1] = forcefield[(ty+1)*w+tx+1] = true;
+ forcefield[ty*w+tx+1] = true;
+ forcefield[(ty+1)*w+tx+1] = true;
board[ty*w+tx+1] = board[(ty+1)*w+tx+1] = EMPTY;
/*
* Didn't work. Revert the merge.
*/
memcpy(board, board2, wh);
- tried_merge[c1 * wh + c2] = tried_merge[c2 * wh + c1] = true;
+ tried_merge[c1 * wh + c2] = true;
+ tried_merge[c2 * wh + c1] = true;
} else {
int c;
dsf_merge(dsf, c1, c2);
c = dsf_canonify(dsf, c1);
for (i = 0; i < wh; i++)
- tried_merge[c*wh+i] = (tried_merge[c1*wh+i] |
+ tried_merge[c*wh+i] = (tried_merge[c1*wh+i] ||
tried_merge[c2*wh+i]);
for (i = 0; i < wh; i++)
- tried_merge[i*wh+c] = (tried_merge[i*wh+c1] |
+ tried_merge[i*wh+c] = (tried_merge[i*wh+c1] ||
tried_merge[i*wh+c2]);
}
}
{
int w = params->w, h = params->h, wh = w*h;
int tx, ty, minmoves;
- unsigned char *board, *forcefield;
+ unsigned char *board;
+ bool *forcefield;
char *ret, *p;
int i;
i++;
} else {
int count = 1;
- int b = board[i], f = forcefield[i];
+ int b = board[i];
+ bool f = forcefield[i];
int c = (b == ANCHOR ? 'a' :
b == MAINANCHOR ? 'm' :
b == EMPTY ? 'e' :
static const char *validate_desc(const game_params *params, const char *desc)
{
int w = params->w, h = params->h, wh = w*h;
- int *active, *link;
+ bool *active;
+ int *link;
int mains = 0;
int i, tx, ty, minmoves;
char *ret;
- active = snewn(wh, int);
+ active = snewn(wh, bool);
link = snewn(wh, int);
i = 0;
state->movecount = 0;
state->imm = snew(struct game_immutable_state);
state->imm->refcount = 1;
- state->imm->forcefield = snewn(wh, unsigned char);
+ state->imm->forcefield = snewn(wh, bool);
i = 0;
while (*desc && *desc != ',') {
- int f = false;
+ bool f = false;
assert(i < wh);
}
struct game_ui {
- int dragging;
+ bool dragging;
int drag_anchor;
int drag_offset_x, drag_offset_y;
int drag_currpos;
- unsigned char *reachable;
+ bool *reachable;
int *bfs_queue; /* used as scratch in interpret_move */
};
ui->dragging = false;
ui->drag_anchor = ui->drag_currpos = -1;
ui->drag_offset_x = ui->drag_offset_y = -1;
- ui->reachable = snewn(wh, unsigned char);
- memset(ui->reachable, 0, wh);
+ ui->reachable = snewn(wh, bool);
+ memset(ui->reachable, 0, wh * sizeof(bool));
ui->bfs_queue = snewn(wh, int);
return ui;
int tilesize;
int w, h;
unsigned long *grid; /* what's currently displayed */
- int started;
+ bool started;
};
static char *interpret_move(const game_state *state, game_ui *ui,
* the anchor, to find all the places to which this block
* can be dragged.
*/
- memset(ui->reachable, false, wh);
+ memset(ui->reachable, 0, wh * sizeof(bool));
qhead = qtail = 0;
ui->reachable[i] = true;
ui->bfs_queue[qtail++] = i;
ui->dragging = false;
ui->drag_anchor = ui->drag_currpos = -1;
ui->drag_offset_x = ui->drag_offset_y = -1;
- memset(ui->reachable, 0, wh);
+ memset(ui->reachable, 0, wh * sizeof(bool));
return str;
} else if (button == ' ' && state->soln) {
return NULL;
}
-static int move_piece(int w, int h, const unsigned char *src,
- unsigned char *dst, unsigned char *ff, int from, int to)
+static bool move_piece(int w, int h, const unsigned char *src,
+ unsigned char *dst, bool *ff, int from, int to)
{
int wh = w*h;
int i, j;
board = snewn(wh, unsigned char);
memcpy(board, state->board, wh);
if (ui->dragging) {
- int mpret = move_piece(w, h, state->board, board,
- state->imm->forcefield,
- ui->drag_anchor, ui->drag_currpos);
+ bool mpret = move_piece(w, h, state->board, board,
+ state->imm->forcefield,
+ ui->drag_anchor, ui->drag_currpos);
assert(mpret);
}
{
game_params *p;
game_state *s;
- char *id = NULL, *desc, *err;
- int count = false;
+ char *id = NULL, *desc;
+ const char *err;
+ bool count = false;
int ret;
int *moves;
return 0;
}
while (1) {
- int moveret;
+ bool moveret;
char *text = board_text_format(s->w, s->h, s->board,
s->imm->forcefield);
game_state *s2;
game_params p;
unsigned char *grid;
int px, py;
- int completed;
+ bool completed;
};
static game_params *default_params(void)
*/
static void sokoban_generate(int w, int h, unsigned char *grid, int moves,
- int nethack, random_state *rs)
+ bool nethack, random_state *rs)
{
struct pull {
int ox, oy, nx, ny, score;
struct game_drawstate {
game_params p;
int tilesize;
- int started;
+ bool started;
unsigned short *grid;
};
{
int w = state->p.w, h = state->p.h;
int px = state->px, py = state->py;
- int dx, dy, nx, ny, nbx, nby, type, m, i, freebarrels, freetargets;
+ int dx, dy, nx, ny, nbx, nby, type, m, i;
+ bool freebarrels, freetargets;
game_state *ret;
if (*move < '1' || *move == '5' || *move > '9' || move[1])
#include "puzzles.h"
#ifdef STANDALONE_SOLVER
-int solver_verbose = false;
+bool solver_verbose = false;
#endif
enum {
struct game_params {
int w2, h2; /* full grid width and height respectively */
- int unique; /* should row and column patterns be unique? */
+ bool unique; /* should row and column patterns be unique? */
int diff;
};
#define DIFFLIST(A) \
struct game_state {
int w2, h2;
- int unique;
+ bool unique;
char *grid;
- unsigned char *immutable;
+ bool *immutable;
- int completed, cheated;
+ bool completed, cheated;
};
static game_params *default_params(void)
return NULL;
}
-static game_state *blank_state(int w2, int h2, int unique)
+static game_state *blank_state(int w2, int h2, bool unique)
{
game_state *state = snew(game_state);
int s = w2 * h2;
state->h2 = h2;
state->unique = unique;
state->grid = snewn(s, char);
- state->immutable = snewn(s, unsigned char);
+ state->immutable = snewn(s, bool);
memset(state->grid, EMPTY, s);
- memset(state->immutable, false, s);
+ memset(state->immutable, 0, s*sizeof(bool));
state->completed = state->cheated = false;
game_state *ret = blank_state(w2, h2, state->unique);
memcpy(ret->grid, state->grid, s);
- memcpy(ret->immutable, state->immutable, s);
+ memcpy(ret->immutable, state->immutable, s*sizeof(bool));
ret->completed = state->completed;
ret->cheated = state->cheated;
}
static int unruly_solver_check_threes(game_state *state, int *rowcount,
- int *colcount, int horizontal,
+ int *colcount, bool horizontal,
char check, char block)
{
int w2 = state->w2, h2 = state->h2;
}
static int unruly_solver_check_uniques(game_state *state, int *rowcount,
- int horizontal, char check, char block,
+ bool horizontal, char check, char block,
struct unruly_scratch *scratch)
{
int w2 = state->w2, h2 = state->h2;
return ret;
}
-static int unruly_solver_fill_row(game_state *state, int i, int horizontal,
+static int unruly_solver_fill_row(game_state *state, int i, bool horizontal,
int *rowcount, int *colcount, char fill)
{
int ret = 0;
}
static int unruly_solver_check_complete_nums(game_state *state,
- int *complete, int horizontal,
+ int *complete, bool horizontal,
int *rowcount, int *colcount,
char fill)
{
}
static int unruly_solver_check_near_complete(game_state *state,
- int *complete, int horizontal,
+ int *complete, bool horizontal,
int *rowcount, int *colcount,
char fill)
{
return ret;
}
-static int unruly_validate_rows(const game_state *state, int horizontal,
+static int unruly_validate_rows(const game_state *state, bool horizontal,
char check, int *errors)
{
int w2 = state->w2, h2 = state->h2;
return ret;
}
-static int unruly_validate_unique(const game_state *state, int horizontal,
+static int unruly_validate_unique(const game_state *state, bool horizontal,
int *errors)
{
int w2 = state->w2, h2 = state->h2;
if (nfull != nc)
continue;
for (r2 = r+1; r2 < nr; r2++) {
- int match = true;
+ bool match = true;
for (c = 0; c < nc; c++)
if (state->grid[r*rmult + c*cmult] !=
state->grid[r2*rmult + c*cmult])
}
static int unruly_validate_counts(const game_state *state,
- struct unruly_scratch *scratch, int *errors)
+ struct unruly_scratch *scratch, bool *errors)
{
int w2 = state->w2, h2 = state->h2;
int w = w2/2, h = h2/2;
- char below = false;
- char above = false;
+ bool below = false;
+ bool above = false;
int i;
/* See if all rows/columns are satisfied. If one is exceeded,
* mark it as an error (if required)
*/
- char hasscratch = true;
+ bool hasscratch = true;
if (!scratch) {
scratch = unruly_new_scratch(state);
hasscratch = false;
* Generator *
* ********* */
-static int unruly_fill_game(game_state *state, struct unruly_scratch *scratch,
- random_state *rs)
+static bool unruly_fill_game(game_state *state, struct unruly_scratch *scratch,
+ random_state *rs)
{
int w2 = state->w2, h2 = state->h2;
{
#ifdef STANDALONE_SOLVER
char *debug;
- int temp_verbose = false;
+ bool temp_verbose = false;
#endif
int w2 = params->w2, h2 = params->h2;
* See if the game has accidentally come out too easy.
*/
if (params->diff > 0) {
- int ok;
+ bool ok;
game_state *solver;
solver = dup_game(state);
unruly_solve_game(solver, scratch, params->diff - 1);
- ok = unruly_validate_counts(solver, scratch, NULL);
+ ok = unruly_validate_counts(solver, scratch, NULL) > 0;
free_game(solver);
unruly_free_scratch(scratch);
struct game_ui {
int cx, cy;
- char cursor;
+ bool cursor;
};
static game_ui *new_ui(const game_state *state)
struct game_drawstate {
int tilesize;
int w2, h2;
- int started;
+ bool started;
int *gridfs;
- int *rowfs;
+ bool *rowfs;
int *grid;
};
ds->started = false;
ds->gridfs = snewn(s, int);
- ds->rowfs = snewn(2 * (w2 + h2), int);
+ ds->rowfs = snewn(2 * (w2 + h2), bool);
ds->grid = snewn(s, int);
for (i = 0; i < s; i++)
/* Keyboard move */
if (IS_CURSOR_MOVE(button)) {
- move_cursor(button, &ui->cx, &ui->cy, w2, h2, 0);
+ move_cursor(button, &ui->cx, &ui->cy, w2, h2, false);
ui->cursor = true;
return UI_UPDATE;
}
ds->gridfs[i] = 0;
unruly_validate_all_rows(state, ds->gridfs);
for (i = 0; i < 2 * (h2 + w2); i++)
- ds->rowfs[i] = 0;
+ ds->rowfs[i] = false;
unruly_validate_counts(state, NULL, ds->rowfs);
for (y = 0; y < h2; y++) {
int *crosses; /* mark edges which are crossed */
#endif
struct graph *graph;
- int completed, cheated, just_solved;
+ bool completed, cheated, just_solved;
};
static int edgecmpC(const void *av, const void *bv)
* between b1 and b2, intersect. We count it as an intersection if
* any of the endpoints lies _on_ the other line.
*/
-static int cross(point a1, point a2, point b1, point b2)
+static bool cross(point a1, point a2, point b1, point b2)
{
long b1x, b1y, b2x, b2y, px, py;
int64 d1, d2, d3;
add234(edges, e);
}
-static int isedge(tree234 *edges, int a, int b)
+static bool isedge(tree234 *edges, int a, int b)
{
edge e;
edges = newtree234(edgecmp);
vlist = snewn(n, vertex);
while (1) {
- int added = false;
+ bool added = false;
for (i = 0; i < n; i++) {
v = index234(vertices, i);
static void mark_crossings(game_state *state)
{
- int ok = true;
+ bool ok = true;
int i, j;
edge *e, *e2;
struct game_ui {
int dragpoint; /* point being dragged; -1 if none */
point newpoint; /* where it's been dragged to so far */
- int just_dragged; /* reset in game_changed_state */
- int just_moved; /* _set_ in game_changed_state */
+ bool just_dragged; /* reset in game_changed_state */
+ bool just_moved; /* _set_ in game_changed_state */
float anim_length;
};
int w, h;
edge *e;
int i, j;
- int bg, points_moved;
+ int bg;
+ bool points_moved;
/*
* There's no terribly sensible way to do partial redraws of
#endif /* NO_HTMLHELP */
enum { NONE, HLP, CHM } help_type;
char *help_path;
-int help_has_contents;
+bool help_has_contents;
#ifndef FILENAME_MAX
#define FILENAME_MAX (260)
HFONT cfgfont;
HBRUSH oldbr;
HPEN oldpen;
- int help_running;
+ bool help_running;
enum { DRAWING, PRINTING, NOTHING } drawstatus;
DOCINFO di;
- int printcount, printw, printh, printsolns, printcurr, printcolour;
+ int printcount, printw, printh;
+ bool printsolns, printcurr, printcolour;
float printscale;
int printoffsetx, printoffsety;
float printpixelscale;
int fontstart;
- int linewidth, linedotted;
+ int linewidth;
+ bool linedotted;
drawing *dr;
int xmin, ymin;
float puzz_scale;
DeleteObject(br);
}
-static void win_set_pen(frontend *fe, int colour, int thin)
+static void win_set_pen(frontend *fe, int colour, bool thin)
{
HPEN pen;
assert(fe->drawstatus != NOTHING);
* furniture (wx,wy).
*/
-static int check_window_resize(frontend *fe, int cx, int cy,
- int *px, int *py,
- int *wx, int *wy)
+static bool check_window_resize(frontend *fe, int cx, int cy,
+ int *px, int *py, int *wx, int *wy)
{
RECT r;
- int x, y, sy = get_statusbar_height(fe), changed = 0;
+ int x, y, sy = get_statusbar_height(fe);
+ bool changed = false;
/* disallow making window thinner than menu bar */
x = max(cx, fe->xmin);
AdjustWindowRectEx(&r, WINFLAGS, true, 0);
*wx = r.right - r.left;
*wy = r.bottom - r.top;
- changed = 1;
+ changed = true;
}
*px = x;
* permissible.
*/
static midend *midend_for_new_game(frontend *fe, const game *cgame,
- char *arg, int maybe_game_id,
- int maybe_save_file, char **error)
+ char *arg, bool maybe_game_id,
+ bool maybe_save_file, char **error)
{
midend *me = NULL;
SetDlgItemTextA(hwnd, IDC_ABOUT_VERSION, ver);
}
#endif
- return true;
+ return 1;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
create_config_controls(fe);
}
#endif
- return true;
+ return 1;
case WM_COMMAND:
/*
hdc = GetDC(fe->hwnd);
SetMapMode(hdc, MM_TEXT);
- fe->dlg_done = false;
+ fe->dlg_done = 0;
fe->cfgfont = CreateFont(-MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72),
0, 0, 0, 0,
#endif
}
-static int get_config(frontend *fe, int which)
+static bool get_config(frontend *fe, int which)
{
#ifdef _WIN32_WCE
fe->cfg_which = which;
hdc = GetDC(fe->hwnd);
SetMapMode(hdc, MM_TEXT);
- fe->dlg_done = false;
+ fe->dlg_done = 0;
fe->cfgfont = CreateFont(-MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72),
0, 0, 0, 0,
mkctrl(fe, col1l, col2r, y, y+height, "BUTTON",
BS_NOTIFY | BS_AUTOCHECKBOX | WS_TABSTOP,
0, i->name, (j->ctlid = id++));
- CheckDlgButton(fe->cfgbox, j->ctlid, (i->u.boolean.bval != 0));
+ CheckDlgButton(fe->cfgbox, j->ctlid, i->u.boolean.bval);
y += height;
break;
* new window size.
*/
-static void adjust_game_size(frontend *fe, RECT *proposed, int isedge,
+static void adjust_game_size(frontend *fe, RECT *proposed, bool isedge,
int *wx_r, int *wy_r)
{
RECT cr, wr;
update_copy_menu_greying(fe);
}
-static int is_alt_pressed(void)
+static bool is_alt_pressed(void)
{
BYTE keystate[256];
int r = GetKeyboardState(keystate);
case WM_SIZING:
{
RECT *sr = (RECT *)lParam;
- int wx, wy, isedge = 0;
+ int wx, wy;
+ bool isedge = false;
if (wParam == WMSZ_TOP ||
wParam == WMSZ_RIGHT ||
wParam == WMSZ_BOTTOM ||
- wParam == WMSZ_LEFT) isedge = 1;
+ wParam == WMSZ_LEFT) isedge = true;
adjust_game_size(fe, sr, isedge, &wx, &wy);
/* Given the window size the puzzles constrain
p = cmdline; q = outputline; outputargc = 0;
while (*p) {
- int quote;
+ bool quote;
/* Skip whitespace searching for start of argument. */
while (*p && isspace(*p)) p++;
outputargv[outputargc] = q;
outputargstart[outputargc] = p;
outputargc++;
- quote = 0;
+ quote = false;
/* Copy data into the argument until it's finished. */
while (*p) {
if (quotes > 0) {
/* Outside a quote segment, a quote starts one. */
- if (!quote) quotes--, quote = 1;
+ if (!quote) quotes--, quote = true;
/* Now we produce (n+1)/3 literal quotes... */
for (i = 3; i <= quotes+1; i += 3) *q++ = '"';