diff -ruN -X /home/jjm/cvs/no.freeciv FreecivCVS/client/gui-gtk/wldlg.c freeciv/client/gui-gtk/wldlg.c --- FreecivCVS/client/gui-gtk/wldlg.c Sun Apr 2 09:46:17 2000 +++ freeciv/client/gui-gtk/wldlg.c Fri May 5 10:37:04 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; ipcity) { can_build = can_build && can_build_unit(pdialog->pcity, i); can_eventually_build = can_eventually_build && diff -ruN -X /home/jjm/cvs/no.freeciv FreecivCVS/client/gui-xaw/wldlg.c freeciv/client/gui-xaw/wldlg.c --- FreecivCVS/client/gui-xaw/wldlg.c Sun Apr 2 09:46:18 2000 +++ freeciv/client/gui-xaw/wldlg.c Fri May 5 10:37:19 2000 @@ -820,8 +820,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; @@ -835,14 +835,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 the 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) @@ -926,14 +942,16 @@ int where) { int target; - int i, len; + int i, idx, len; /* Is there anything selected to insert? */ if (retAvail->list_index == XAW_LIST_NONE) return; + idx = retAvail->list_index; + /* Pick out the target and its type. */ - target = pdialog->worklist_avail_ids[retAvail->list_index]; + target = pdialog->worklist_avail_ids[idx]; if (retAvail->list_index >= pdialog->worklist_avail_num_targets) { /* target is a global worklist id */ @@ -946,13 +964,19 @@ if (where < MAX_LEN_WORKLIST) where++; } + + /* Update the list of available targets */ + worklist_populate_targets(pdialog); + XawListChange(pdialog->avail, pdialog->worklist_avail_names_ptrs, + 0, 0, False); + /* note no target selected */ } else if (retAvail->list_index >= 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++; } @@ -968,6 +992,16 @@ if (where < len) XawListHighlight(pdialog->worklist, where); + + if (idx < pdialog->worklist_avail_num_improvements) { + /* Update the list of available targets */ + worklist_populate_targets(pdialog); + XawListChange(pdialog->avail, pdialog->worklist_avail_names_ptrs, + 0, 0, False); + + /* Select the next available target */ + XawListHighlight(pdialog->avail, idx); + } } /**************************************************************** @@ -978,12 +1012,21 @@ { struct worklist_dialog *pdialog = (struct worklist_dialog *)client_data; XawListReturnStruct *retList = XawListShowCurrent(pdialog->worklist); - int i, j, k; + XawListReturnStruct *retAvail = XawListShowCurrent(pdialog->avail); + int i, j, k, id, avail_idx, avail_id, avail_num_improvements; + avail_idx = avail_id = avail_num_improvements = 0; if (retList->list_index == XAW_LIST_NONE) return; k = retList->list_index; + id = pdialog->worklist_ids[k]; + + if (retAvail->list_index != XAW_LIST_NONE) { + avail_idx = retAvail->list_index; + 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++) @@ -1012,6 +1055,23 @@ 0, 0, False); if (k < i) XawListHighlight(pdialog->worklist, k); + + if (id < B_LAST) { + /* Update the list of available targets */ + worklist_populate_targets(pdialog); + XawListChange(pdialog->avail, pdialog->worklist_avail_names_ptrs, + 0, 0, False); + /* Select the avail item previously selected */ + if (retAvail->list_index != XAW_LIST_NONE) { + /* 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++; + } + XawListHighlight(pdialog->avail, avail_idx); + } + } } @@ -1266,11 +1326,11 @@ *****************************************************************/ void worklist_populate_targets(struct worklist_dialog *pdialog) { - int i, n; + int i, j, n; struct player *pplr = game.player_ptr; Boolean b; int advanced_tech; - int can_build, can_eventually_build; + int can_build, can_eventually_build, is_building; n = 0; @@ -1289,6 +1349,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); @@ -1296,8 +1368,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]; @@ -1308,11 +1381,11 @@ /* + Second, units. */ for(i=0; ipcity) { can_build = can_build && can_build_unit(pdialog->pcity, i); can_eventually_build = can_eventually_build && diff -ruN -X /home/jjm/cvs/no.freeciv FreecivCVS/server/cityturn.c freeciv/server/cityturn.c --- FreecivCVS/server/cityturn.c Wed May 3 09:17:02 2000 +++ freeciv/server/cityturn.c Fri May 5 10:28:45 2000 @@ -971,13 +971,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? */ @@ -1013,12 +1014,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! */ @@ -1028,6 +1030,7 @@ get_unit_type(new_target)->name, pcity->name); target = new_target; + pcity->worklist->ids[i-1] = target + B_LAST; } } else if (!is_unit && !can_build_improvement(pcity, target)) { int new_target = improvement_upgrades_to(pcity, target); @@ -1054,11 +1057,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! */ @@ -1068,20 +1072,20 @@ get_impr_name_ex(pcity, new_target), pcity->name); target = new_target; + pcity->worklist->ids[i-1] = target; } } - /* 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)) { diff -ruN -X /home/jjm/cvs/no.freeciv FreecivCVS/server/plrhand.c freeciv/server/plrhand.c --- FreecivCVS/server/plrhand.c Wed May 3 09:17:02 2000 +++ freeciv/server/plrhand.c Fri May 5 17:06:12 2000 @@ -78,6 +78,12 @@ }; static void update_player_aliveness(struct player *pplayer); +static Unit_Type_id player_unit_upgrades_to(struct player *pplayer, + Unit_Type_id id); +static int player_improvement_upgrades_to(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; @@ -1366,6 +1372,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); } @@ -1389,6 +1396,91 @@ map_know_and_see_all(pplayer); } } +} + +/************************************************************************** +... +**************************************************************************/ +static Unit_Type_id player_unit_upgrades_to(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_improvement_upgrades_to(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_unit_upgrades_to(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_improvement_upgrades_to(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]); } /**************************************************************************