From e8e85c5762da65ef7fa6e49ee8cc61f132be6d34 Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Tue, 21 Nov 2017 19:28:16 -0500 Subject: puzzles: resync with upstream; add Loopy and Palisade, mouse mode This brings a various small changes to the drawing and input code, as well as a brand new "mouse mode", where input goes to a virtual mouse cursor. Only Loopy has this mouse mode enabled by default, while other games have it hidden away under the debug menu. Some changes by me to Palisade were required to make it playable; those are included here as well. Right now, sgt-net is pushing the c200v2's upper limit on size and may have to be dropped in a future commit. Change-Id: I495d2a2125462c2985aec1ffbc54bbe3fe5133bd --- apps/plugins/puzzles/src/LICENCE | 5 +- apps/plugins/puzzles/src/filling.c | 2 +- apps/plugins/puzzles/src/grid.c | 96 +++++++++++++++++++++++++++++++++++++ apps/plugins/puzzles/src/grid.h | 1 + apps/plugins/puzzles/src/loopy.c | 3 ++ apps/plugins/puzzles/src/palisade.c | 21 ++++++-- 6 files changed, 122 insertions(+), 6 deletions(-) (limited to 'apps/plugins/puzzles/src') diff --git a/apps/plugins/puzzles/src/LICENCE b/apps/plugins/puzzles/src/LICENCE index 4235005ea7..ce0418e6cc 100644 --- a/apps/plugins/puzzles/src/LICENCE +++ b/apps/plugins/puzzles/src/LICENCE @@ -1,8 +1,9 @@ This software is copyright (c) 2004-2014 Simon Tatham. Portions copyright Richard Boulton, James Harvey, Mike Pinna, Jonas -Kölker, Dariusz Olszewski, Michael Schierl, Lambros Lambrou, Bernd -Schmidt, Steffen Bauer, Lennard Sprong and Rogier Goossens. +Kölker, Dariusz Olszewski, Michael Schierl, Lambros Lambrou, Bernd +Schmidt, Steffen Bauer, Lennard Sprong, Rogier Goossens and Michael +Quevillon. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files diff --git a/apps/plugins/puzzles/src/filling.c b/apps/plugins/puzzles/src/filling.c index 7e71eb25b4..231de4c079 100644 --- a/apps/plugins/puzzles/src/filling.c +++ b/apps/plugins/puzzles/src/filling.c @@ -1,6 +1,6 @@ /* -*- tab-width: 8; indent-tabs-mode: t -*- * filling.c: An implementation of the Nikoli game fillomino. - * Copyright (C) 2007 Jonas Kölker. See LICENSE for the license. + * Copyright (C) 2007 Jonas Kölker. See LICENSE for the license. */ /* TODO: diff --git a/apps/plugins/puzzles/src/grid.c b/apps/plugins/puzzles/src/grid.c index 52648e5a92..b5e6bb0937 100644 --- a/apps/plugins/puzzles/src/grid.c +++ b/apps/plugins/puzzles/src/grid.c @@ -2060,6 +2060,102 @@ static grid *grid_new_greathexagonal(int width, int height, const char *desc) return g; } +#define KAGOME_TILESIZE 18 +/* Vector for side of triangle - ratio is close to sqrt(3) */ +#define KAGOME_A 15 +#define KAGOME_B 26 + +static void grid_size_kagome(int width, int height, + int *tilesize, int *xextent, int *yextent) +{ + int a = KAGOME_A; + int b = KAGOME_B; + + *tilesize = KAGOME_TILESIZE; + *xextent = (4*a) * (width-1) + 6*a; + *yextent = (2*b) * (height-1) + 2*b; +} + +static grid *grid_new_kagome(int width, int height, const char *desc) +{ + int x, y; + int a = KAGOME_A; + int b = KAGOME_B; + + /* Upper bounds - don't have to be exact */ + int max_faces = 6 * (width + 1) * (height + 1); + int max_dots = 6 * width * height; + + tree234 *points; + + grid *g = grid_empty(); + g->tilesize = KAGOME_TILESIZE; + g->faces = snewn(max_faces, grid_face); + g->dots = snewn(max_dots, grid_dot); + + points = newtree234(grid_point_cmp_fn); + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + grid_dot *d; + /* centre of hexagon */ + int px = (4*a) * x; + int py = (2*b) * y; + if (y % 2) + px += 2*a; + + /* hexagon */ + grid_face_add_new(g, 6); + d = grid_get_dot(g, points, px + a, py - b); grid_face_set_dot(g, d, 0); + d = grid_get_dot(g, points, px + 2*a, py ); grid_face_set_dot(g, d, 1); + d = grid_get_dot(g, points, px + a, py + b); grid_face_set_dot(g, d, 2); + d = grid_get_dot(g, points, px - a, py + b); grid_face_set_dot(g, d, 3); + d = grid_get_dot(g, points, px - 2*a, py ); grid_face_set_dot(g, d, 4); + d = grid_get_dot(g, points, px - a, py - b); grid_face_set_dot(g, d, 5); + + /* Triangle above right */ + if ((x < width - 1) || (!(y % 2) && y)) { + grid_face_add_new(g, 3); + d = grid_get_dot(g, points, px + 3*a, py - b); grid_face_set_dot(g, d, 0); + d = grid_get_dot(g, points, px + 2*a, py ); grid_face_set_dot(g, d, 1); + d = grid_get_dot(g, points, px + a, py - b); grid_face_set_dot(g, d, 2); + } + + /* Triangle below right */ + if ((x < width - 1) || (!(y % 2) && (y < height - 1))) { + grid_face_add_new(g, 3); + d = grid_get_dot(g, points, px + 3*a, py + b); grid_face_set_dot(g, d, 0); + d = grid_get_dot(g, points, px + a, py + b); grid_face_set_dot(g, d, 1); + d = grid_get_dot(g, points, px + 2*a, py ); grid_face_set_dot(g, d, 2); + } + + /* Left triangles */ + if (!x && (y % 2)) { + /* Triangle above left */ + grid_face_add_new(g, 3); + d = grid_get_dot(g, points, px - a, py - b); grid_face_set_dot(g, d, 0); + d = grid_get_dot(g, points, px - 2*a, py ); grid_face_set_dot(g, d, 1); + d = grid_get_dot(g, points, px - 3*a, py - b); grid_face_set_dot(g, d, 2); + + /* Triangle below left */ + if (y < height - 1) { + grid_face_add_new(g, 3); + d = grid_get_dot(g, points, px - a, py + b); grid_face_set_dot(g, d, 0); + d = grid_get_dot(g, points, px - 3*a, py + b); grid_face_set_dot(g, d, 1); + d = grid_get_dot(g, points, px - 2*a, py ); grid_face_set_dot(g, d, 2); + } + } + } + } + + freetree234(points); + assert(g->num_faces <= max_faces); + assert(g->num_dots <= max_dots); + + grid_make_consistent(g); + return g; +} + #define OCTAGONAL_TILESIZE 40 /* b/a approx sqrt(2) */ #define OCTAGONAL_A 29 diff --git a/apps/plugins/puzzles/src/grid.h b/apps/plugins/puzzles/src/grid.h index 19079a44b8..26d0b16633 100644 --- a/apps/plugins/puzzles/src/grid.h +++ b/apps/plugins/puzzles/src/grid.h @@ -100,6 +100,7 @@ typedef struct grid { A(SNUBSQUARE,snubsquare) \ A(CAIRO,cairo) \ A(GREATHEXAGONAL,greathexagonal) \ + A(KAGOME,kagome) \ A(OCTAGONAL,octagonal) \ A(KITE,kites) \ A(FLORET,floret) \ diff --git a/apps/plugins/puzzles/src/loopy.c b/apps/plugins/puzzles/src/loopy.c index 5f1940e945..c14412d6be 100644 --- a/apps/plugins/puzzles/src/loopy.c +++ b/apps/plugins/puzzles/src/loopy.c @@ -278,6 +278,7 @@ static void check_caches(const solver_state* sstate); A("Penrose (kite/dart)",PENROSE_P2,3,3) \ A("Penrose (rhombs)",PENROSE_P3,3,3) \ A("Great-Great-Dodecagonal",GREATGREATDODECAGONAL,2,2) \ + A("Kagome",KAGOME,3,3) \ /* end of list */ #define GRID_NAME(title,type,amin,omin) title, @@ -544,6 +545,7 @@ static const game_params loopy_presets_more[] = { #ifdef SMALL_SCREEN { 7, 7, DIFF_HARD, LOOPY_GRID_HONEYCOMB }, { 5, 4, DIFF_HARD, LOOPY_GRID_GREATHEXAGONAL }, + { 5, 4, DIFF_HARD, LOOPY_GRID_KAGOME }, { 5, 5, DIFF_HARD, LOOPY_GRID_OCTAGONAL }, { 3, 3, DIFF_HARD, LOOPY_GRID_FLORET }, { 3, 3, DIFF_HARD, LOOPY_GRID_DODECAGONAL }, @@ -552,6 +554,7 @@ static const game_params loopy_presets_more[] = { #else { 10, 10, DIFF_HARD, LOOPY_GRID_HONEYCOMB }, { 5, 4, DIFF_HARD, LOOPY_GRID_GREATHEXAGONAL }, + { 5, 4, DIFF_HARD, LOOPY_GRID_KAGOME }, { 7, 7, DIFF_HARD, LOOPY_GRID_OCTAGONAL }, { 5, 5, DIFF_HARD, LOOPY_GRID_FLORET }, { 5, 4, DIFF_HARD, LOOPY_GRID_DODECAGONAL }, diff --git a/apps/plugins/puzzles/src/palisade.c b/apps/plugins/puzzles/src/palisade.c index 5227a1d56c..e495bbed2c 100644 --- a/apps/plugins/puzzles/src/palisade.c +++ b/apps/plugins/puzzles/src/palisade.c @@ -865,14 +865,16 @@ static char *game_text_format(const game_state *state) struct game_ui { int x, y; - unsigned int show: 1; + unsigned int show: 1; + unsigned int fake_ctrl: 1; + unsigned int fake_shift: 1; }; static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); ui->x = ui->y = 0; - ui->show = FALSE; + ui->show = ui->fake_ctrl = ui->fake_shift = FALSE; return ui; } @@ -916,7 +918,10 @@ static char *interpret_move(const game_state *state, game_ui *ui, 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; + int control = (button & MOD_CTRL) | ui->fake_ctrl, shift = (button & MOD_SHFT) | ui->fake_shift; + + /* reset */ + ui->fake_ctrl = ui->fake_shift = FALSE; button &= ~MOD_MASK; @@ -999,6 +1004,16 @@ static char *interpret_move(const game_state *state, game_ui *ui, return UI_UPDATE; } } + else if(IS_CURSOR_SELECT(button)) { + /* CURSOR_SELECT or CURSOR_SELECT2 tells us to toggle whether + * the button press should be interpreted as having CTRL or + * shift pressed along with it, respectively. */ + ui->show = TRUE; + if(button == CURSOR_SELECT2) + ui->fake_shift = !ui->fake_shift; + else + ui->fake_ctrl = !ui->fake_ctrl; + } return NULL; } -- cgit v1.2.3