[Freeciv-Dev] Dynamic worklists
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Hi all,
Just updating my dynamic worklists patch.
Now in the gtk client:
- when inserting a global worklist, the targets list is updated.
- when inserting an improvement, the targets list is updated and the item
after the target is reselected (and the scroll recenters on it)
- when deleting an improvement, the targets list is updated, and the
target last selected is reselected and recentered.
In the server:
- the server now processes the whole of each cities worklist, and upgrades
anything it can/deletes anything obsolete
- added functions to do similar processing to a player's global worklist
every turn. This could probably be optimized later by only doing this when
something happens that would require it: discovered a tech, built a
wonder, gained/lost a wonder etc.
This pretty much does what was suggested earlier
Richard
--------
Richard Atkins rja@xxxxxxxxxxx
http://www.pcug.org.au/~rja/
"All these moments will be lost in
time, like tears in the rain."
Blade Runner
--------
--- cvs-freeciv/server/cityturn.c Mon Apr 24 16:25:50 2000
+++ mod-freeciv/server/cityturn.c Tue Apr 25 13:02:17 2000
@@ -959,13 +959,14 @@
{
int success = 0;
int i;
+ int change_target_idx = 0;
if (worklist_is_empty(pcity->worklist))
/* Nothing in the worklist; bail now. */
return 0;
i = 0;
- while (1) {
+ while (i < MAX_LEN_WORKLIST) {
int target, is_unit;
/* What's the next item in the worklist? */
@@ -1001,12 +1002,13 @@
/* Maybe we can just upgrade the target to what the city /can/ build. */
if (new_target == target) {
- /* Nope, we're stuck. Dump this item from the worklist. */
- notify_player_ex(pplayer, pcity->x, pcity->y, E_CITY_CANTBUILD,
- _("Game: %s can't build %s from the worklist; "
- "tech not yet available. Postponing..."),
- pcity->name,
- get_unit_type(target)->name);
+ /* Nope, we're stuck. Postpone until we can build target. */
+ if (!success)
+ notify_player_ex(pplayer, pcity->x, pcity->y, E_CITY_CANTBUILD,
+ _("Game: %s can't build %s from the worklist; "
+ "tech not yet available. Postponing..."),
+ pcity->name,
+ get_unit_type(target)->name);
continue;
} else {
/* Yep, we can go after new_target instead. Joy! */
@@ -1042,11 +1044,12 @@
we can build. */
if (new_target == target) {
/* Nope, no use. *sigh* */
- notify_player_ex(pplayer, pcity->x, pcity->y, E_CITY_CANTBUILD,
- _("Game: %s can't build %s from the worklist; "
- "tech not yet available. Postponing..."),
- pcity->name,
- get_impr_name_ex(pcity, target));
+ if (!success)
+ notify_player_ex(pplayer, pcity->x, pcity->y, E_CITY_CANTBUILD,
+ _("Game: %s can't build %s from the worklist; "
+ "tech not yet available. Postponing..."),
+ pcity->name,
+ get_impr_name_ex(pcity, target));
continue;
} else {
/* Hey, we can upgrade the improvement! */
@@ -1059,17 +1062,16 @@
}
}
- /* All okay. Switch targets. */
- change_build_target(pplayer, pcity, target, is_unit, E_WORKLIST);
-
- success = 1;
- break;
+ if (!success) {
+ /* All okay. Switch targets. */
+ change_build_target(pplayer, pcity, target, is_unit, E_WORKLIST);
+ change_target_idx = i-1;
+ success = 1;
+ }
}
if (success) {
- /* i is the index immediately _after_ the item we're changing to.
- Remove the (i-1)th item from the worklist. */
- worklist_remove(pcity->worklist, i-1);
+ worklist_remove(pcity->worklist, change_target_idx);
}
if (worklist_is_empty(pcity->worklist)) {
--- cvs-freeciv/server/plrhand.c Wed Apr 19 14:53:48 2000
+++ mod-freeciv/server/plrhand.c Tue Apr 25 12:56:02 2000
@@ -77,6 +77,12 @@
};
static void update_player_aliveness(struct player *pplayer);
+static Unit_Type_id player_upgrade_unit(struct player *pplayer,
+ Unit_Type_id id);
+static int player_upgrade_improvement(struct player *pplayer, int imp);
+static void update_player_worklist(struct player *pplayer,
+ struct worklist *pwl);
+static void update_player_worklists(struct player *pplayer);
struct player_score_entry {
int idx;
@@ -1362,6 +1368,7 @@
if (city_list_size(&pplayer->cities)) /* has to be below the above for
got_tech */
update_tech(pplayer, city_list_size(&pplayer->cities));
#endif
+ update_player_worklists(pplayer);
update_unit_activities(pplayer);
update_player_aliveness(pplayer);
}
@@ -1385,6 +1392,78 @@
map_know_and_see_all(pplayer);
}
}
+}
+
+static Unit_Type_id player_upgrade_unit(struct player *pplayer,
+ Unit_Type_id id)
+{
+ Unit_Type_id latest_ok = id;
+ if (!can_player_build_unit_direct(pplayer, id))
+ return -1;
+ while (unit_type_exists(id = unit_types[id].obsoleted_by))
+ if (can_player_build_unit_direct(pplayer, id))
+ latest_ok = id;
+
+ return latest_ok;
+}
+
+static int player_upgrade_improvement(struct player *pplayer, int imp)
+{
+ if (imp == B_BARRACKS && can_player_build_improvement(pplayer, B_BARRACKS3))
+ return B_BARRACKS3;
+ else if (imp == B_BARRACKS &&
+ can_player_build_improvement(pplayer, B_BARRACKS2))
+ return B_BARRACKS2;
+ else if (imp == B_BARRACKS2 &&
+ can_player_build_improvement(pplayer, B_BARRACKS3))
+ return B_BARRACKS3;
+ else
+ return imp;
+}
+
+static void update_player_worklist(struct player *pplayer,
+ struct worklist *pwl)
+{
+ int i, target, is_unit, new_target;
+
+ i = 0;
+ while (i < MAX_LEN_WORKLIST) {
+ if (!worklist_peek_ith(pwl, &target, &is_unit, i))
+ break;
+ i++;
+ if (is_unit && !can_player_eventually_build_unit(pplayer, target)) {
+ new_target = player_upgrade_unit(pplayer, target);
+ if (!can_player_eventually_build_unit(pplayer, new_target)) {
+ /* Nope, the player can't build this target, ever. */
+ /* purge this worklist item. */
+ worklist_remove(pwl, i-1);
+ i--;
+ continue;
+ }
+ /* new_target is what will go in the list */
+ target = new_target;
+ pwl->ids[i-1] = target+B_LAST;
+ } else if (!is_unit &&
+ !could_player_eventually_build_improvement(pplayer, target)) {
+ new_target = player_upgrade_improvement(pplayer, target);
+ if(!could_player_eventually_build_improvement(pplayer, new_target)) {
+ worklist_remove(pwl, i-1);
+ i--;
+ continue;
+ }
+ /* new_target is what will go in the list */
+ target = new_target;
+ pwl->ids[i-1] = target;
+ }
+ }
+}
+
+static void update_player_worklists(struct player *pplayer)
+{
+ int i;
+ for (i = 0; i < MAX_NUM_WORKLISTS; i++)
+ if (pplayer->worklists[i].is_valid)
+ update_player_worklist(pplayer, &pplayer->worklists[i]);
}
/**************************************************************************
--- cvs-freeciv/client/gui-gtk/wldlg.c Sun Apr 2 20:54:39 2000
+++ mod-freeciv/client/gui-gtk/wldlg.c Tue Apr 25 13:27:56 2000
@@ -793,8 +793,8 @@
void insert_into_worklist(struct worklist_dialog *pdialog,
int before, int id)
{
- int i, first_free;
- int target, is_unit;
+ int i, j, first_free;
+ int target, is_unit, is_building;
if (id >= B_LAST) {
target = id - B_LAST;
@@ -808,14 +808,30 @@
really can (eventually) build the target. We've made sure that
the list of available targets is okay for this city, but a global
worklist may try to insert an odd-ball unit or target. */
- if (pdialog->pcity &&
- ((is_unit && !can_eventually_build_unit(pdialog->pcity, target)) ||
- (!is_unit && !can_eventually_build_improvement(pdialog->pcity,
target))))
- /* Nope, this city can't build this target, ever. Don't put it into
- the worklist. */
- return;
-
-
+ if (pdialog->pcity) {
+ if ((is_unit && !can_eventually_build_unit(pdialog->pcity, target)) ||
+ (!is_unit &&
+ !can_eventually_build_improvement(pdialog->pcity, target))) {
+ /* Nope, this city can't build this target, ever. Don't put it into
+ the worklist. */
+ return;
+ }
+ if (!is_unit && can_eventually_build_improvement(pdialog->pcity, target)) {
+ j = 0;
+ is_building = FALSE;
+ while ((j < MAX_LEN_WORKLIST) &&
+ (pdialog->worklist_ids[j] != WORKLIST_END)) {
+ if (pdialog->worklist_ids[j] == target) {
+ is_building = TRUE;
+ break;
+ }
+ j++;
+ }
+ if (is_building)
+ /* city is already building this item, so don't add it. */
+ return;
+ }
+ }
/* Find the first free element in the worklist */
for (first_free = 0; first_free < MAX_LEN_WORKLIST; first_free++)
if (pdialog->worklist_ids[first_free] == WORKLIST_END)
@@ -918,12 +934,17 @@
if (where < MAX_LEN_WORKLIST)
where++;
}
+
+ /* Update the list of available targets */
+ worklist_populate_targets(pdialog);
+ update_clist(pdialog->avail, pdialog->worklist_avail_names_ptrs);
+ /* note no target selected */
} else if (idx >= pdialog->worklist_avail_num_improvements) {
- /* target is an improvement or wonder */
+ /* target is a unit */
insert_into_worklist(pdialog, where, target+B_LAST);
where++;
} else {
- /* target is a unit */
+ /* target is an improvement or wonder */
insert_into_worklist(pdialog, where, target);
where++;
}
@@ -937,8 +958,20 @@
break;
/* Re-select the item that was previously selected. */
- if (where < len)
+ if (where < len) {
gtk_clist_select_row((GtkCList *)pdialog->worklist, where, 0);
+ gtk_clist_moveto((GtkCList *)pdialog->worklist, where, 0, 0.5, 0);
+ }
+
+ if (idx < pdialog->worklist_avail_num_improvements) {
+ /* Update the list of available targets */
+ worklist_populate_targets(pdialog);
+ update_clist(pdialog->avail, pdialog->worklist_avail_names_ptrs);
+
+ /* Select the next available target */
+ gtk_clist_select_row((GtkCList *)pdialog->avail, idx, 0);
+ gtk_clist_moveto((GtkCList *)pdialog->avail, idx, 0, 0.5, 0);
+ }
}
/****************************************************************
@@ -948,12 +981,21 @@
{
struct worklist_dialog *pdialog = (struct worklist_dialog *)data;
GList *selection = GTK_CLIST(pdialog->worklist)->selection;
- int i, j, k;
+ GList *avail_selection = GTK_CLIST(pdialog->avail)->selection;
+ int i, j, k, id, avail_idx, avail_id, avail_num_improvements;
+ avail_idx = avail_id = avail_num_improvements = 0;
if (! selection)
return;
k = (int)selection->data;
+ id = pdialog->worklist_ids[k];
+
+ if (avail_selection != NULL) {
+ avail_idx = (int)avail_selection->data;
+ avail_id = pdialog->worklist_avail_ids[avail_idx];
+ avail_num_improvements = pdialog->worklist_avail_num_improvements;
+ }
/* Find the last element in the worklist */
for (i = 0; i < MAX_LEN_WORKLIST; i++)
@@ -982,8 +1024,28 @@
/* Select the item immediately after the item we just deleted,
if there is such an item. */
- if (k < i)
+ if (k < i) {
gtk_clist_select_row((GtkCList *)pdialog->worklist, k, 0);
+ gtk_clist_moveto((GtkCList *)pdialog->worklist, k, 0, 0.5, 0);
+ }
+
+ if (id < B_LAST) {
+ /* Update the list of available targets */
+ worklist_populate_targets(pdialog);
+ update_clist(pdialog->avail, pdialog->worklist_avail_names_ptrs);
+
+ /* Select the avail item previously selected */
+ if (avail_selection != NULL) {
+ /* id *might* have been inserted in the list */
+ if ((id < avail_id) && (avail_num_improvements <
+ pdialog->worklist_avail_num_improvements)) {
+ /* id is in the list before what was selected */
+ avail_idx++;
+ }
+ gtk_clist_select_row((GtkCList *)pdialog->avail, avail_idx, 0);
+ gtk_clist_moveto((GtkCList *)pdialog->avail, avail_idx, 0, 0.5, 0);
+ }
+ }
}
/****************************************************************
@@ -1230,10 +1292,10 @@
*****************************************************************/
void worklist_populate_targets(struct worklist_dialog *pdialog)
{
- int i, n;
+ int i, j, n;
struct player *pplr = game.player_ptr;
int advanced_tech;
- int can_build, can_eventually_build;
+ int can_build, can_eventually_build, is_building;
n = 0;
@@ -1253,6 +1315,18 @@
can_build = can_player_build_improvement(pplr,i);
can_eventually_build = could_player_eventually_build_improvement(pplr,i);
+ /* Is the player already going to build this improvement? */
+ j = 0;
+ is_building = FALSE;
+ while ((j < MAX_LEN_WORKLIST) &&
+ (pdialog->worklist_ids[j] != WORKLIST_END)) {
+ if (pdialog->worklist_ids[j] == i) {
+ is_building = TRUE;
+ break;
+ }
+ j++;
+ }
+
/* If there's a city, can the city build the improvement? */
if (pdialog->pcity) {
can_build = can_build && can_build_improvement(pdialog->pcity, i);
@@ -1260,8 +1334,9 @@
can_eventually_build_improvement(pdialog->pcity, i);
}
- if (( advanced_tech && can_eventually_build) ||
- (!advanced_tech && can_build)) {
+ if ((( advanced_tech && can_eventually_build) ||
+ (!advanced_tech && can_build)) &&
+ !is_building) {
worklist_id_to_name(pdialog->worklist_avail_names[n],
i, 0, pdialog->pcity);
pdialog->worklist_avail_names_ptrs[n]=pdialog->worklist_avail_names[n];
@@ -1272,11 +1347,11 @@
/* + Second, units. */
for(i=0; i<game.num_unit_types; i++) {
- /* Can the player (eventually) build this improvement? */
+ /* Can the player (eventually) build this unit? */
can_build = can_player_build_unit(pplr,i);
can_eventually_build = can_player_eventually_build_unit(pplr,i);
- /* If there's a city, can the city build the improvement? */
+ /* If there's a city, can the city build the unit? */
if (pdialog->pcity) {
can_build = can_build && can_build_unit(pdialog->pcity, i);
can_eventually_build = can_eventually_build &&
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Freeciv-Dev] Dynamic worklists,
Richard Atkins <=
|
|