shithub: puzzles

Download patch

ref: ed9b669b295001915b0b42084256837a99efecaf
parent: a03b4b467fe513c3ce868ca7e722fb041324fc6f
author: Simon Tatham <anakin@pobox.com>
date: Tue May 11 15:24:22 EDT 2004

Now we have the UI abstraction, use it to implement keyboard control
in Net.

[originally from svn r4214]

--- a/net.c
+++ b/net.c
@@ -724,13 +724,24 @@
     return active;
 }
 
+struct game_ui {
+    int cur_x, cur_y;
+    int cur_visible;
+};
+
 game_ui *new_ui(game_state *state)
 {
-    return NULL;
+    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);
 }
 
 /* ----------------------------------------------------------------------
@@ -738,32 +749,61 @@
  */
 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 (x % TILE_SIZE >= TILE_SIZE - TILE_BORDER ||
-	y % 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
      * cannot be turned, and is visually marked as being locked.
@@ -785,7 +825,7 @@
      * locked tile.
      */
     if (tile(state, tx, ty) & LOCKED)
-	return NULL;
+	return nullret;
 
     /*
      * Otherwise, turn the tile one way or the other. Left button
@@ -987,7 +1027,7 @@
 }
 
 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;
@@ -1023,6 +1063,26 @@
               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);
@@ -1269,10 +1329,13 @@
 
             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;