#define TILE_BORDER 1
#define WINDOW_OFFSET 16
-#define ROTATE_TIME 0.1F
-#define FLASH_FRAME 0.05F
+#define ROTATE_TIME 0.13F
+#define FLASH_FRAME 0.07F
enum {
COL_BACKGROUND,
* Randomly select a new game seed.
*/
-char *new_game_seed(game_params *params)
+char *new_game_seed(game_params *params, random_state *rs)
{
/*
* The full description of a Net game is far too large to
* understand it and do something completely different.)
*/
char buf[40];
- sprintf(buf, "%d", rand());
+ sprintf(buf, "%lu", random_bits(rs, 32));
return dupstr(buf);
}
+char *validate_seed(game_params *params, char *seed)
+{
+ /*
+ * Since any string at all will suffice to seed the RNG, there
+ * is no validation required.
+ */
+ return NULL;
+}
+
/* ----------------------------------------------------------------------
* Construct an initial game state, given a seed and parameters.
*/
return active;
}
+struct game_ui {
+ int cur_x, cur_y;
+ int cur_visible;
+};
+
+game_ui *new_ui(game_state *state)
+{
+ game_ui *ui = snew(game_ui);
+ ui->cur_x = state->width / 2;
+ ui->cur_y = state->height / 2;
+ ui->cur_visible = FALSE;
+
+ return ui;
+}
+
+void free_ui(game_ui *ui)
+{
+ sfree(ui);
+}
+
/* ----------------------------------------------------------------------
* Process a move.
*/
-game_state *make_move(game_state *state, int x, int y, int button)
+game_state *make_move(game_state *state, game_ui *ui, int x, int y, int button)
{
- game_state *ret;
+ game_state *ret, *nullret;
int tx, ty, orig;
- /*
- * All moves in Net are made with the mouse.
- */
- if (button != LEFT_BUTTON &&
- button != MIDDLE_BUTTON &&
- button != RIGHT_BUTTON)
- return NULL;
+ nullret = NULL;
- /*
- * The button must have been clicked on a valid tile.
- */
- x -= WINDOW_OFFSET + TILE_BORDER;
- y -= WINDOW_OFFSET + TILE_BORDER;
- if (x < 0 || y < 0)
- return NULL;
- tx = x / TILE_SIZE;
- ty = y / TILE_SIZE;
- if (tx >= state->width || ty >= state->height)
- return NULL;
- if (tx % TILE_SIZE >= TILE_SIZE - TILE_BORDER ||
- ty % TILE_SIZE >= TILE_SIZE - TILE_BORDER)
- return NULL;
+ if (button == LEFT_BUTTON ||
+ button == MIDDLE_BUTTON ||
+ button == RIGHT_BUTTON) {
+
+ if (ui->cur_visible) {
+ ui->cur_visible = FALSE;
+ nullret = state;
+ }
+
+ /*
+ * The button must have been clicked on a valid tile.
+ */
+ x -= WINDOW_OFFSET + TILE_BORDER;
+ y -= WINDOW_OFFSET + TILE_BORDER;
+ if (x < 0 || y < 0)
+ return nullret;
+ tx = x / TILE_SIZE;
+ ty = y / TILE_SIZE;
+ if (tx >= state->width || ty >= state->height)
+ return nullret;
+ if (x % TILE_SIZE >= TILE_SIZE - TILE_BORDER ||
+ y % TILE_SIZE >= TILE_SIZE - TILE_BORDER)
+ return nullret;
+ } else if (button == CURSOR_UP || button == CURSOR_DOWN ||
+ button == CURSOR_RIGHT || button == CURSOR_LEFT) {
+ if (button == CURSOR_UP && ui->cur_y > 0)
+ ui->cur_y--;
+ else if (button == CURSOR_DOWN && ui->cur_y < state->height-1)
+ ui->cur_y++;
+ else if (button == CURSOR_LEFT && ui->cur_x > 0)
+ ui->cur_x--;
+ else if (button == CURSOR_RIGHT && ui->cur_x < state->width-1)
+ ui->cur_x++;
+ else
+ return nullret; /* no cursor movement */
+ ui->cur_visible = TRUE;
+ return state; /* UI activity has occurred */
+ } else if (button == 'a' || button == 's' || button == 'd' ||
+ button == 'A' || button == 'S' || button == 'D') {
+ tx = ui->cur_x;
+ ty = ui->cur_y;
+ if (button == 'a' || button == 'A')
+ button = LEFT_BUTTON;
+ else if (button == 's' || button == 'S')
+ button = MIDDLE_BUTTON;
+ else if (button == 'd' || button == 'D')
+ button = RIGHT_BUTTON;
+ } else
+ return nullret;
/*
* The middle button locks or unlocks a tile. (A locked tile
* locked tile.
*/
if (tile(state, tx, ty) & LOCKED)
- return NULL;
+ return nullret;
/*
* Otherwise, turn the tile one way or the other. Left button
}
static void draw_tile(frontend *fe, game_state *state, int x, int y, int tile,
- float angle)
+ float angle, int cursor)
{
int bx = WINDOW_OFFSET + TILE_SIZE * x;
int by = WINDOW_OFFSET + TILE_SIZE * y;
tile & LOCKED ? COL_LOCKED : COL_BACKGROUND);
/*
+ * Draw an inset outline rectangle as a cursor, in whichever of
+ * COL_LOCKED and COL_BACKGROUND we aren't currently drawing
+ * in.
+ */
+ if (cursor) {
+ draw_line(fe, bx+TILE_SIZE/8, by+TILE_SIZE/8,
+ bx+TILE_SIZE/8, by+TILE_SIZE-TILE_SIZE/8,
+ tile & LOCKED ? COL_BACKGROUND : COL_LOCKED);
+ draw_line(fe, bx+TILE_SIZE/8, by+TILE_SIZE/8,
+ bx+TILE_SIZE-TILE_SIZE/8, by+TILE_SIZE/8,
+ tile & LOCKED ? COL_BACKGROUND : COL_LOCKED);
+ draw_line(fe, bx+TILE_SIZE-TILE_SIZE/8, by+TILE_SIZE/8,
+ bx+TILE_SIZE-TILE_SIZE/8, by+TILE_SIZE-TILE_SIZE/8,
+ tile & LOCKED ? COL_BACKGROUND : COL_LOCKED);
+ draw_line(fe, bx+TILE_SIZE/8, by+TILE_SIZE-TILE_SIZE/8,
+ bx+TILE_SIZE-TILE_SIZE/8, by+TILE_SIZE-TILE_SIZE/8,
+ tile & LOCKED ? COL_BACKGROUND : COL_LOCKED);
+ }
+
+ /*
* Set up the rotation matrix.
*/
matrix[0] = (float)cos(angle * PI / 180.0);
}
void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
- game_state *state, float t, float ft)
+ game_state *state, game_ui *ui, float t, float ft)
{
int x, y, tx, ty, frame;
unsigned char *active;
if (index(state, ds->visible, x, y) != c ||
index(state, ds->visible, x, y) == 0xFF ||
- (x == tx && y == ty)) {
+ (x == tx && y == ty) ||
+ (ui->cur_visible && x == ui->cur_x && y == ui->cur_y)) {
draw_tile(fe, state, x, y, c,
- (x == tx && y == ty ? angle : 0.0F));
- if (x == tx && y == ty)
+ (x == tx && y == ty ? angle : 0.0F),
+ (ui->cur_visible && x == ui->cur_x && y == ui->cur_y));
+ if ((x == tx && y == ty) ||
+ (ui->cur_visible && x == ui->cur_x && y == ui->cur_y))
index(state, ds->visible, x, y) = 0xFF;
else
index(state, ds->visible, x, y) = c;