| CODENOTIFIER | HelpYou are not signed inSign in |
Project: Freeciv
Revision: 15184
Author: cazfi
Date: 28 Aug 2008 17:07:34
Changes:Save ongoing base building activity by base number and not
by base type specific actions.
See #40462
Files:| ... | ...@@ -234,6 +234,8 @@ | |
| 234 | 234 | ;/* savefile_options_default */ |
| 235 | 235 | |
| 236 | 236 | static const char hex_chars[] = "0123456789abcdef"; |
| 237 | static const char num_chars[] = | |
| 238 | "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+"; | |
| 237 | 239 | |
| 238 | 240 | static void set_savegame_special(bv_special *specials, bv_bases *bases, |
| 239 | 241 | char ch, const enum tile_special_type *index); |
| ... | ...@@ -277,6 +279,34 @@ | |
| 277 | 279 | } |
| 278 | 280 | |
| 279 | 281 | /**************************************************************************** |
| 282 | Converts number in to single character. This works to values up to ~70. | |
| 283 | ****************************************************************************/ | |
| 284 | static char num2char(unsigned int num) | |
| 285 | { | |
| 286 | if (num >= strlen(num_chars)) { | |
| 287 | return '?'; | |
| 288 | } | |
| 289 | ||
| 290 | return num_chars[num]; | |
| 291 | } | |
| 292 | ||
| 293 | /**************************************************************************** | |
| 294 | Converts single character into numerical value. This is not hex conversion. | |
| 295 | ****************************************************************************/ | |
| 296 | static int char2num(char ch) | |
| 297 | { | |
| 298 | char *pch; | |
| 299 | ||
| 300 | pch = strchr(num_chars, ch); | |
| 301 | ||
| 302 | if (!pch) { | |
| 303 | die("Unknown ascii value for num: '%c' %d", ch, ch); | |
| 304 | } | |
| 305 | ||
| 306 | return pch - num_chars; | |
| 307 | } | |
| 308 | ||
| 309 | /**************************************************************************** | |
| 280 | 310 | Dereferences the terrain character. See terrains[].identifier |
| 281 | 311 | example: char2terrain('a') => T_ARCTIC |
| 282 | 312 | ****************************************************************************/ |
| ... | ...@@ -1581,7 +1611,8 @@ | |
| 1581 | 1611 | ****************************************************************************/ |
| 1582 | 1612 | static void player_load_units(struct player *plr, int plrno, |
| 1583 | 1613 | struct section_file *file, |
| 1584 | char *savefile_options) | |
| 1614 | char *savefile_options, | |
| 1615 | struct base_type **base_order) | |
| 1585 | 1616 | { |
| 1586 | 1617 | int nunits, i, j; |
| 1587 | 1618 | enum unit_activity activity; |
| ... | ...@@ -1599,7 +1630,8 @@ | |
| 1599 | 1630 | const char* type_name; |
| 1600 | 1631 | struct unit_type *type; |
| 1601 | 1632 | struct base_type *pbase = NULL; |
| 1602 | ||
| 1633 | int base; | |
| 1634 | ||
| 1603 | 1635 | type_name = secfile_lookup_str_default(file, NULL, |
| 1604 | 1636 | "player%d.u%d.type_by_name", |
| 1605 | 1637 | plrno, i); |
| ... | ...@@ -1660,6 +1692,9 @@ | |
| 1660 | 1692 | punit->birth_turn = secfile_lookup_int_default(file, game.info.turn, |
| 1661 | 1693 | "player%d.u%d.born", plrno, i); |
| 1662 | 1694 | activity = secfile_lookup_int(file, "player%d.u%d.activity", plrno, i); |
| 1695 | base = secfile_lookup_int_default(file, -1, | |
| 1696 | "player%d.u%d.activity_base", plrno, i); | |
| 1697 | ||
| 1663 | 1698 | if (activity == ACTIVITY_PATROL_UNUSED) { |
| 1664 | 1699 | /* Previously ACTIVITY_PATROL and ACTIVITY_GOTO were used for |
| 1665 | 1700 | * client-side goto. Now client-side goto is handled by setting |
| ... | ...@@ -1676,10 +1711,14 @@ | |
| 1676 | 1711 | } else if (activity == ACTIVITY_AIRBASE) { |
| 1677 | 1712 | pbase = get_base_by_gui_type(BASE_GUI_AIRBASE, punit, punit->tile); |
| 1678 | 1713 | } else if (activity == ACTIVITY_BASE) { |
| 1679 | /* This should currently not happen as ACTIVITY_BASE is saved as | |
| 1680 | * ACTIVITY_FORTRESS or ACTIVITY_AIRBASE. We don't know base type, | |
| 1681 | * let's use sensible fallback */ | |
| 1682 | set_unit_activity_base(punit, BASE_FORTRESS); | |
| 1714 | if (base >= 0 | |
| 1715 | && base < sizeof(base_order) / sizeof (struct base_type *)) { | |
| 1716 | pbase = base_order[base]; | |
| 1717 | } else { | |
| 1718 | freelog(LOG_ERROR, "Cannot find base %d for %s to build", | |
| 1719 | base, unit_rule_name(punit)); | |
| 1720 | set_unit_activity(punit, ACTIVITY_IDLE); | |
| 1721 | } | |
| 1683 | 1722 | } else { |
| 1684 | 1723 | set_unit_activity(punit, activity); |
| 1685 | 1724 | } |
| ... | ...@@ -1764,7 +1803,7 @@ | |
| 1764 | 1803 | int len = secfile_lookup_int_default(file, 0, |
| 1765 | 1804 | "player%d.u%d.orders_length", plrno, i); |
| 1766 | 1805 | if (len > 0) { |
| 1767 | char *orders_buf, *dir_buf, *act_buf; | |
| 1806 | char *orders_buf, *dir_buf, *act_buf, *base_buf; | |
| 1768 | 1807 | |
| 1769 | 1808 | punit->orders.list = fc_malloc(len * sizeof(*(punit->orders.list))); |
| 1770 | 1809 | punit->orders.length = len; |
| ... | ...@@ -1781,6 +1820,8 @@ | |
| 1781 | 1820 | "player%d.u%d.dir_list", plrno, i); |
| 1782 | 1821 | act_buf = secfile_lookup_str_default(file, "", |
| 1783 | 1822 | "player%d.u%d.activity_list", plrno, i); |
| 1823 | base_buf = secfile_lookup_str_default(file, NULL, | |
| 1824 | "player%d.u%d.base_list", plrno, i); | |
| 1784 | 1825 | punit->has_orders = TRUE; |
| 1785 | 1826 | for (j = 0; j < len; j++) { |
| 1786 | 1827 | struct unit_order *order = &punit->orders.list[j]; |
| ... | ...@@ -1806,6 +1847,7 @@ | |
| 1806 | 1847 | break; |
| 1807 | 1848 | } |
| 1808 | 1849 | |
| 1850 | /* Pre 2.2 savegames had activities ACTIVITY_FORTRESS and ACTIVITY_AIRBASE */ | |
| 1809 | 1851 | if (order->activity == ACTIVITY_FORTRESS) { |
| 1810 | 1852 | pbase = get_base_by_gui_type(BASE_GUI_FORTRESS, NULL, NULL); |
| 1811 | 1853 | order->activity = ACTIVITY_IDLE; /* In case no matching gui_type found */ |
| ... | ...@@ -1813,11 +1855,23 @@ | |
| 1813 | 1855 | pbase = get_base_by_gui_type(BASE_GUI_AIRBASE, NULL, NULL); |
| 1814 | 1856 | order->activity = ACTIVITY_IDLE; /* In case no matching gui_type found */ |
| 1815 | 1857 | } |
| 1816 | ||
| 1817 | 1858 | if (pbase) { |
| 1818 | 1859 | /* Either ACTIVITY_FORTRESS or ACTIVITY_AIRBASE */ |
| 1819 | 1860 | order->activity = ACTIVITY_BASE; |
| 1820 | 1861 | order->base = base_number(pbase); |
| 1862 | } else if (base_buf) { | |
| 1863 | base = char2num(base_buf[j]); | |
| 1864 | ||
| 1865 | if (base >= 0 | |
| 1866 | && base < sizeof(base_order) / sizeof (struct base_type *)) { | |
| 1867 | pbase = base_order[base]; | |
| 1868 | } else { | |
| 1869 | freelog(LOG_ERROR, "Cannot find base %d for %s to build", | |
| 1870 | base, unit_rule_name(punit)); | |
| 1871 | base = base_number(get_base_by_gui_type(BASE_GUI_FORTRESS, NULL, NULL)); | |
| 1872 | } | |
| 1873 | ||
| 1874 | order->base = base; | |
| 1821 | 1875 | } |
| 1822 | 1876 | } |
| 1823 | 1877 | } else { |
| ... | ...@@ -3313,6 +3367,7 @@ | |
| 3313 | 3367 | |
| 3314 | 3368 | unit_list_iterate(plr->units, punit) { |
| 3315 | 3369 | int activity = punit->activity; |
| 3370 | char basenum = -1; | |
| 3316 | 3371 | |
| 3317 | 3372 | i++; |
| 3318 | 3373 | |
| ... | ...@@ -3329,17 +3384,7 @@ | |
| 3329 | 3384 | plrno, i); |
| 3330 | 3385 | |
| 3331 | 3386 | if (activity == ACTIVITY_BASE) { |
| 3332 | struct base_type *pbase; | |
| 3333 | pbase = base_by_number(punit->activity_base); | |
| 3334 | ||
| 3335 | if (pbase->gui_type == BASE_GUI_FORTRESS) { | |
| 3336 | activity = ACTIVITY_FORTRESS; | |
| 3337 | } else if (pbase->gui_type == BASE_GUI_AIRBASE) { | |
| 3338 | activity = ACTIVITY_AIRBASE; | |
| 3339 | } else { | |
| 3340 | /* Gui type other. Make sensible fallback */ | |
| 3341 | activity = ACTIVITY_FORTRESS; | |
| 3342 | } | |
| 3387 | basenum = punit->activity_base; | |
| 3343 | 3388 | } |
| 3344 | 3389 | secfile_insert_int(file, activity, "player%d.u%d.activity", |
| 3345 | 3390 | plrno, i); |
| ... | ...@@ -3349,6 +3394,7 @@ | |
| 3349 | 3394 | secfile_insert_int(file, punit->activity_target, |
| 3350 | 3395 | "player%d.u%d.activity_target", |
| 3351 | 3396 | plrno, i); |
| 3397 | secfile_insert_int(file, basenum, "player%d.u%d.activity_base", plrno, i); | |
| 3352 | 3398 | secfile_insert_bool(file, punit->done_moving, |
| 3353 | 3399 | "player%d.u%d.done_moving", plrno, i); |
| 3354 | 3400 | secfile_insert_int(file, punit->moves_left, "player%d.u%d.moves", |
| ... | ...@@ -3389,7 +3435,7 @@ | |
| 3389 | 3435 | "player%d.u%d.transported_by", plrno, i); |
| 3390 | 3436 | if (punit->has_orders) { |
| 3391 | 3437 | int len = punit->orders.length, j; |
| 3392 | char orders_buf[len + 1], dir_buf[len + 1], act_buf[len + 1]; | |
| 3438 | char orders_buf[len + 1], dir_buf[len + 1], act_buf[len + 1], base_buf[len + 1]; | |
| 3393 | 3439 | |
| 3394 | 3440 | secfile_insert_int(file, len, "player%d.u%d.orders_length", plrno, i); |
| 3395 | 3441 | secfile_insert_int(file, punit->orders.index, |
| ... | ...@@ -3403,26 +3449,16 @@ | |
| 3403 | 3449 | orders_buf[j] = order2char(punit->orders.list[j].order); |
| 3404 | 3450 | dir_buf[j] = '?'; |
| 3405 | 3451 | act_buf[j] = '?'; |
| 3452 | base_buf[j] = '?'; | |
| 3406 | 3453 | switch (punit->orders.list[j].order) { |
| 3407 | 3454 | case ORDER_MOVE: |
| 3408 | 3455 | dir_buf[j] = dir2char(punit->orders.list[j].dir); |
| 3409 | 3456 | break; |
| 3410 | 3457 | case ORDER_ACTIVITY: |
| 3411 | 3458 | if (punit->orders.list[j].activity == ACTIVITY_BASE) { |
| 3412 | struct base_type *pbase; | |
| 3413 | pbase = base_by_number(punit->orders.list[j].base); | |
| 3414 | ||
| 3415 | if (pbase->gui_type == BASE_GUI_FORTRESS) { | |
| 3416 | act_buf[j] = activity2char(ACTIVITY_FORTRESS); | |
| 3417 | } else if (pbase->gui_type == BASE_GUI_AIRBASE) { | |
| 3418 | act_buf[j] = activity2char(ACTIVITY_AIRBASE); | |
| 3419 | } else { | |
| 3420 | /* Saving others as fortress */ | |
| 3421 | act_buf[j] = activity2char(ACTIVITY_FORTRESS); | |
| 3422 | } | |
| 3423 | } else { | |
| 3424 | act_buf[j] = activity2char(punit->orders.list[j].activity); | |
| 3459 | base_buf[j] = num2char(punit->orders.list[j].base); | |
| 3425 | 3460 | } |
| 3461 | act_buf[j] = activity2char(punit->orders.list[j].activity); | |
| 3426 | 3462 | break; |
| 3427 | 3463 | case ORDER_FULL_MP: |
| 3428 | 3464 | case ORDER_BUILD_CITY: |
| ... | ...@@ -3442,6 +3478,8 @@ | |
| 3442 | 3478 | "player%d.u%d.dir_list", plrno, i); |
| 3443 | 3479 | secfile_insert_str(file, act_buf, |
| 3444 | 3480 | "player%d.u%d.activity_list", plrno, i); |
| 3481 | secfile_insert_str(file, base_buf, | |
| 3482 | "player%d.u%d.base_list", plrno, i); | |
| 3445 | 3483 | } else { |
| 3446 | 3484 | /* Put all the same fields into the savegame - otherwise the |
| 3447 | 3485 | * registry code can't correctly use a tabular format and the |
| ... | ...@@ -3458,6 +3496,8 @@ | |
| 3458 | 3496 | "player%d.u%d.dir_list", plrno, i); |
| 3459 | 3497 | secfile_insert_str(file, "-", |
| 3460 | 3498 | "player%d.u%d.activity_list", plrno, i); |
| 3499 | secfile_insert_str(file, "-", | |
| 3500 | "player%d.u%d.base_list", plrno, i); | |
| 3461 | 3501 | } |
| 3462 | 3502 | } unit_list_iterate_end; |
| 3463 | 3503 | } |
| ... | ...@@ -4517,7 +4557,7 @@ | |
| 4517 | 4557 | |
| 4518 | 4558 | player_load_cities(pplayer, n, file, savefile_options, |
| 4519 | 4559 | improvement_order, improvement_order_size); |
| 4520 | player_load_units(pplayer, n, file, savefile_options); | |
| 4560 | player_load_units(pplayer, n, file, savefile_options, base_order); | |
| 4521 | 4561 | player_load_attributes(pplayer, n, file); |
| 4522 | 4562 | } players_iterate_end; |
| 4523 | 4563 |