Complete.Org: Mailing Lists: Archives: freeciv-dev: November 2003:
[Freeciv-Dev] Re: (PR#6948) Quickselect unit
Home

[Freeciv-Dev] Re: (PR#6948) Quickselect unit

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] Re: (PR#6948) Quickselect unit
From: "Arnstein Lindgard" <a-l@xxxxxxx>
Date: Tue, 25 Nov 2003 12:11:27 -0800
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=6948 >

On Tue, 25 Nov 2003 10:42:32 -0800 Mike Kaufman wrote:
> it's not to style spec.

Ok, new patch. But which do you think is more readable in this
particular case? Explicitness is an interesting topic, which is
related to clarity of mind, and giving reasons is always helpful.
When skipping brackets, you may loose the ability to easily expand a
segment. In this case I did it to tell myself that the segment in
question should remain simple; at the end of the function, one and
only one value must be returned. If you prefere 2) then maybe you have
developed the traditional speed-reading skill of skimming a page in
diagonals with your eyes?

When many if's exist within other if's, using brackets only for those
that need it, help me see the big picture faster. I never read K&R
and sure as hell never will, but I want to comply with Freeciv
CodingStyle. I'm not particularly bothered with any style or having
to comply with it. I don't want to be argumentative, I only hope you
may find occasional different views to cause you to constantly
question and rethink, like I do. If I annoyed you just a little bit,
I succeded. I quite often re-indent and re-style my code just in
order to see if I can wrap my mind around the problem in a different
way.

1)

  if (qtype == SELECT_SEA) {
    if      (panytransporter) return panytransporter;
    else if (panymovesea)     return panymovesea;
    else if (panysea)         return panysea;
    else if (panymoveunit)    return panymoveunit;
    else if (panyunit)        return panyunit;
  }
  else if (qtype == SELECT_LAND) {
    if      (panymoveland)    return panymoveland;
    else if (panyland)        return panyland;
    else if (panymovesea)     return panymovesea;
    else if (panysea)         return panysea;
    else if (panymoveunit)    return panymoveunit;
    else if (panyunit)        return panyunit;
  }
  return NULL;

2)

  if (qtype == SELECT_SEA) {
    if (panytransporter) {
      return panytransporter;
    } else if (panymovesea) {
      return panymovesea;
    } else if (panysea) {
      return panysea;
    } else if (panymoveunit) {
      return panymoveunit;
    } else if (panyunit) {
      return panyunit;
    }
  }
  else if (qtype == SELECT_LAND) {
    if (panymoveland) {
      return panymoveland;
    } else if (panyland) {
      return panyland;
    } else if (panymovesea) {
      return panymovesea;
    } else if (panysea) {
      return panysea;
    } else if (panymoveunit) {
      return panymoveunit;
    } else if (panyunit) {
      return panyunit;
    }
  }
  return NULL;


Arnstein


diff -ruN -Xdiff_ignore freeciv/client/control.c quickselect2/client/control.c
--- freeciv/client/control.c    Sat Nov 22 23:37:20 2003
+++ quickselect2/client/control.c       Tue Nov 25 20:36:38 2003
@@ -73,6 +73,8 @@
 
 static struct unit *find_best_focus_candidate(bool accept_current);
 static void store_focus(void);
+static struct unit *quickselect(struct tile *ptile,
+                        enum quickselect_type qtype);
 
 /**************************************************************************
 ...
@@ -1298,7 +1300,7 @@
 /**************************************************************************
  Handles everything when the user clicked a tile
 **************************************************************************/
-void do_map_click(int xtile, int ytile)
+void do_map_click(int xtile, int ytile, enum quickselect_type qtype)
 {
   struct city *pcity = map_get_city(xtile, ytile);
   struct tile *ptile = map_get_tile(xtile, ytile);
@@ -1336,7 +1338,18 @@
     update_unit_info_label(punit);
     return;
   }
-  
+
+  /* Bypass stack popup if quickselect is specified. */
+  if (qtype) {
+    struct unit *qunit = quickselect(ptile, qtype);
+    if (qunit) {
+      set_unit_focus_and_select(qunit);
+    }
+    return;
+  }
+
+  /* Otherwise use popups. */
+
   if (pcity && game.player_idx==pcity->owner) {
     popup_city_dialog(pcity, FALSE);
     return;
@@ -1365,6 +1378,124 @@
 }
 
 /**************************************************************************
+ Quickselecting a unit is normally done with <control> left/right click.
+ Bypassing the stack popup is quite convenient, and can be tactically
+ important in furious multiplayer games.
+**************************************************************************/
+static struct unit *quickselect(struct tile *ptile,
+                          enum quickselect_type qtype)
+{
+  int listsize = unit_list_size(&ptile->units);
+  struct unit *panytransporter = NULL,
+              *panymovesea  = NULL, *panysea  = NULL,
+              *panymoveland = NULL, *panyland = NULL,
+              *panymoveunit = NULL, *panyunit = NULL;
+
+  assert(qtype > SELECT_POPUP);
+
+  if (listsize == 0) {
+    return NULL;
+  } else if (listsize == 1) {
+    struct unit *punit = unit_list_get(&ptile->units, 0);
+    return (game.player_idx == punit->owner) ? punit : NULL;
+  }
+
+  /*  Quickselect priorities. Units with moves left
+   *  before exhausted. Focus unit is excluded.
+   *
+   *    SEA:  Transporter
+   *          Sea unit
+   *          Any unit
+   *
+   *    LAND: Military land unit
+   *          Non-combatant
+   *          Sea unit
+   *          Any unit
+   */
+
+    unit_list_iterate(ptile->units, punit)  {
+  if(game.player_idx != punit->owner || punit == punit_focus) {
+    continue;
+  }
+  if (qtype == SELECT_SEA) {
+    /* Transporter. */
+    if (get_transporter_capacity(punit)) {
+      if (punit->moves_left > 0) {
+        return punit;
+      } else if (!panytransporter) {
+        panytransporter = punit;
+      }
+    }
+    /* Any sea, pref. moves left. */
+    else if (is_sailing_unit(punit)) {
+      if (punit->moves_left > 0) {
+        if (!panymovesea) {
+          panymovesea = punit;
+        }
+      } else if (!panysea) {
+          panysea = punit;
+      }
+    }
+  } else if (qtype == SELECT_LAND) {
+    if (is_ground_unit(punit))  {
+      if (punit->moves_left > 0) {
+        if (is_military_unit(punit)) {
+          return punit;
+        } else if (!panymoveland) {
+            panymoveland = punit;
+        }
+      } else if (!panyland) {
+        panyland = punit;
+      }
+    }
+    else if (is_sailing_unit(punit)) {
+      if (punit->moves_left > 0) {
+        panymovesea = punit;
+      } else {
+        panysea = punit;
+      }
+    }
+  }
+  if (punit->moves_left > 0 && !panymoveunit) {
+    panymoveunit = punit;
+  }
+  if (!panyunit) {
+    panyunit = punit;
+  }
+    } unit_list_iterate_end;
+
+  if (qtype == SELECT_SEA) {
+    if (panytransporter) {
+      return panytransporter;
+    } else if (panymovesea) {
+      return panymovesea;
+    } else if (panysea) {
+      return panysea;
+    } else if (panymoveunit) {
+      return panymoveunit;
+    } else if (panyunit) {
+      return panyunit;
+    }
+  }
+  else if (qtype == SELECT_LAND) {
+    if (panymoveland) {
+      return panymoveland;
+    } else if (panyland) {
+      return panyland;
+    } else if (panymovesea) {
+      return panymovesea;
+    } else if (panysea) {
+      return panysea;
+    } else if (panymoveunit) {
+      return panymoveunit;
+    } else if (panyunit) {
+      return panyunit;
+    }
+  }
+  return NULL;
+}
+
+/**************************************************************************
  Finish the goto mode and let the unit which is stored in hover_unit move
  to a given location.
 **************************************************************************/
diff -ruN -Xdiff_ignore freeciv/client/control.h quickselect2/client/control.h
--- freeciv/client/control.h    Wed Nov 19 18:32:57 2003
+++ quickselect2/client/control.h       Mon Nov 24 22:34:56 2003
@@ -24,6 +24,11 @@
   HOVER_PATROL
 };
 
+/* Selecting unit from a stack without popup. */
+enum quickselect_type {
+  SELECT_POPUP = 0, SELECT_SEA, SELECT_LAND
+};
+
 extern int hover_unit; /* unit hover_state applies to */
 extern enum cursor_hover_state hover_state;
 extern bool draw_goto_line;
@@ -34,7 +39,7 @@
 void do_unit_nuke(struct unit *punit);
 void do_unit_paradrop_to(struct unit *punit, int x, int y);
 void do_unit_patrol_to(struct unit *punit, int x, int y);
-void do_map_click(int xtile, int ytile);
+void do_map_click(int xtile, int ytile, enum quickselect_type qtype);
 
 void set_hover_state(struct unit *punit, enum cursor_hover_state state);
 void request_center_focus_unit(void);
diff -ruN -Xdiff_ignore freeciv/client/gui-gtk/mapctrl.c 
quickselect2/client/gui-gtk/mapctrl.c
--- freeciv/client/gui-gtk/mapctrl.c    Fri Nov 14 13:30:55 2003
+++ quickselect2/client/gui-gtk/mapctrl.c       Mon Nov 24 21:58:33 2003
@@ -226,6 +226,10 @@
     if ((ev->state & GDK_SHIFT_MASK) && (ev->state & GDK_CONTROL_MASK)) {
       adjust_workers_button_pressed(ev->x, ev->y);
     }
+    /* <CONTROL> + LMB : Quickselect a sea unit. */
+    else if (ev->state & GDK_CONTROL_MASK) {
+      action_button_pressed(ev->x, ev->y, SELECT_SEA);
+    }
     /* <SHIFT> + LMB: Copy Production. */
     else if(is_real && (ev->state & GDK_SHIFT_MASK)) {
       clipboard_copy_production(xtile, ytile);
@@ -238,9 +242,7 @@
     }
     /* Plain LMB click. */
     else {
-      if (is_real) {
-        action_button_pressed(ev->x, ev->y);
-      }
+      action_button_pressed(ev->x, ev->y, SELECT_POPUP);
     }
     break;
 
@@ -258,8 +260,12 @@
 
   case 3: /* RIGHT mouse button */
 
+    /* <CONTROL> + RMB : Quickselect a land unit. */
+    if (ev->state & GDK_CONTROL_MASK) {
+      action_button_pressed(ev->x, ev->y, SELECT_LAND);
+    }
     /* <SHIFT> + RMB: Paste Production. */
-    if(ev->state & GDK_SHIFT_MASK) {
+    else if(ev->state & GDK_SHIFT_MASK) {
       clipboard_paste_production(pcity);
       cancel_tile_hiliting();
     }
diff -ruN -Xdiff_ignore freeciv/client/gui-gtk-2.0/mapctrl.c 
quickselect2/client/gui-gtk-2.0/mapctrl.c
--- freeciv/client/gui-gtk-2.0/mapctrl.c        Fri Nov 14 13:30:56 2003
+++ quickselect2/client/gui-gtk-2.0/mapctrl.c   Mon Nov 24 23:11:01 2003
@@ -206,6 +206,10 @@
     if ((ev->state & GDK_SHIFT_MASK) && (ev->state & GDK_CONTROL_MASK)) {
       adjust_workers_button_pressed(ev->x, ev->y);
     }
+    /* <CONTROL> + LMB : Quickselect a sea unit. */
+    else if (ev->state & GDK_CONTROL_MASK) {
+      action_button_pressed(ev->x, ev->y, SELECT_SEA);
+    }
     /* <SHIFT> + LMB: Copy Production. */
     else if(is_real && (ev->state & GDK_SHIFT_MASK)) {
       clipboard_copy_production(xtile, ytile);
@@ -218,9 +222,7 @@
     }
     /* Plain LMB click. */
     else {
-      if (is_real) {
-        action_button_pressed(ev->x, ev->y);
-      }
+      action_button_pressed(ev->x, ev->y, SELECT_POPUP);
     }
     break;
 
@@ -238,8 +240,12 @@
 
   case 3: /* RIGHT mouse button */
 
+    /* <CONTROL> + RMB : Quickselect a land unit. */
+    if (ev->state & GDK_CONTROL_MASK) {
+      action_button_pressed(ev->x, ev->y, SELECT_LAND);
+    }
     /* <SHIFT> + RMB: Paste Production. */
-    if(ev->state & GDK_SHIFT_MASK) {
+    else if(ev->state & GDK_SHIFT_MASK) {
       clipboard_paste_production(pcity);
       cancel_tile_hiliting();
     }
diff -ruN -Xdiff_ignore freeciv/client/gui-sdl/mapctrl.c 
quickselect2/client/gui-sdl/mapctrl.c
--- freeciv/client/gui-sdl/mapctrl.c    Fri Nov 14 13:30:56 2003
+++ quickselect2/client/gui-sdl/mapctrl.c       Mon Nov 24 23:12:45 2003
@@ -1888,7 +1888,7 @@
        }                     
       }
     } else {
-      action_button_pressed(pButtonEvent->x, pButtonEvent->y);
+      action_button_pressed(pButtonEvent->x, pButtonEvent->y, SELECT_POPUP);
     }
   } else {
     if (pButtonEvent->button == SDL_BUTTON_MIDDLE) {
diff -ruN -Xdiff_ignore freeciv/client/gui-win32/mapctrl.c 
quickselect2/client/gui-win32/mapctrl.c
--- freeciv/client/gui-win32/mapctrl.c  Fri Nov 14 13:30:56 2003
+++ quickselect2/client/gui-win32/mapctrl.c     Mon Nov 24 23:13:47 2003
@@ -238,7 +238,7 @@
                                    LOWORD(lParam), HIWORD(lParam))) {
       popit(LOWORD(lParam),HIWORD(lParam),xtile,ytile);
     } else {
-      action_button_pressed(LOWORD(lParam), HIWORD(lParam));
+      action_button_pressed(LOWORD(lParam), HIWORD(lParam), SELECT_POPUP);
     }
     break;
   case WM_MBUTTONDOWN:
diff -ruN -Xdiff_ignore freeciv/client/gui-xaw/mapctrl.c 
quickselect2/client/gui-xaw/mapctrl.c
--- freeciv/client/gui-xaw/mapctrl.c    Fri Nov 14 13:30:56 2003
+++ quickselect2/client/gui-xaw/mapctrl.c       Mon Nov 24 23:35:01 2003
@@ -207,11 +207,15 @@
     return;
   }
 
-  if (ev->button == Button1) {
-    action_button_pressed(ev->x, ev->y);
-  } else if (canvas_to_map_pos(&x, &y, ev->x, ev->y)
-            && (ev->button == Button2 || ev->state & ControlMask)) {
+  if (ev->button == Button1 && (ev->state & ControlMask)) {
+    action_button_pressed(ev->x, ev->y, SELECT_SEA);
+  } else if (ev->button == Button1) {
+    action_button_pressed(ev->x, ev->y, SELECT_POPUP);
+  } else if (ev->button == Button2 &&
+             canvas_to_map_pos(&x, &y, ev->x, ev->y)) {
     popit(ev->x, ev->y, x, y);
+  } else if (ev->button == Button3 && (ev->state & ControlMask)) {
+    action_button_pressed(ev->x, ev->y, SELECT_LAND);
   } else if (ev->button == Button3) {
     recenter_button_pressed(ev->x, ev->y);
   }
diff -ruN -Xdiff_ignore freeciv/client/mapctrl_common.c 
quickselect2/client/mapctrl_common.c
--- freeciv/client/mapctrl_common.c     Mon Nov 17 19:27:28 2003
+++ quickselect2/client/mapctrl_common.c        Mon Nov 24 21:54:11 2003
@@ -423,7 +423,8 @@
   left-click) is pressed.  For more sophisticated user control use (or
   write) a different xxx_button_pressed function.
 **************************************************************************/
-void action_button_pressed(int canvas_x, int canvas_y)
+void action_button_pressed(int canvas_x, int canvas_y,
+                enum quickselect_type qtype)
 {
   int map_x, map_y;
 
@@ -431,7 +432,7 @@
     /* FIXME: Some actions here will need to check can_client_issue_orders.
      * But all we can check is the lowest common requirement. */
     if (canvas_to_map_pos(&map_x, &map_y, canvas_x, canvas_y)) {
-      do_map_click(map_x, map_y);
+      do_map_click(map_x, map_y, qtype);
     }
   }
 }
diff -ruN -Xdiff_ignore freeciv/client/mapctrl_common.h 
quickselect2/client/mapctrl_common.h
--- freeciv/client/mapctrl_common.h     Fri Nov 14 13:30:54 2003
+++ quickselect2/client/mapctrl_common.h        Mon Nov 24 22:36:26 2003
@@ -17,6 +17,8 @@
 #include "map.h"               /* enum direction8 */
 #include "shared.h"            /* bool type */
 
+#include "control.h"            /* quickselect_type */
+
 extern bool rbutton_down;
 extern bool rectangle_active;
 extern bool tiles_hilited_cities;
@@ -34,7 +36,8 @@
 void release_right_button(int canvas_x, int canvas_y);
 bool get_turn_done_button_state(void);
 void scroll_mapview(enum direction8 gui_dir);
-void action_button_pressed(int canvas_x, int canvas_y);
+void action_button_pressed(int canvas_x, int canvas_y,
+                enum quickselect_type qtype);
 void wakeup_button_pressed(int canvas_x, int canvas_y);
 void adjust_workers_button_pressed(int canvas_x, int canvas_y);
 void recenter_button_pressed(int canvas_x, int canvas_y);

[Prev in Thread] Current Thread [Next in Thread]