Advertisement
Guest User

civdos barbarian units ai (fix 5)

a guest
Apr 9th, 2020
477
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.50 KB | None | 0 0
  1. //CIV 1 BARBARIAN UNIT LOGIC
  2.  
  3. #define IM_CITY       1
  4. #define IM_IRRIGATION 2
  5. #define IM_MINE       4
  6.  
  7. #define SQ_OCEAN     10
  8.  
  9. #define UR_DEFENCE    2 //land defence: only musketeers. In theory also militia, phalanx, riflemen and mech. inf.
  10. #define UR_TRANSPORT  5 //sail or frigate (in theory also trireme and transport)
  11.  
  12. #define UD_LAND       0 //land unit
  13. #define UD_FLEET      2 //unit is a boat
  14.  
  15. #define U_DIPLOMAT 0x2A
  16.  
  17. change_x[9] = {0,0,1,1,1,0,-1,-1,-1};
  18. change_y[9] = {0,-1,-1,0,1,1,1,0,-1};
  19.  
  20. check_ZOC(civ,x,y)
  21. {
  22.     res = 0;
  23.     impr = get_improvements(x,y);
  24.     if ((impr & IM_CITY) == 0)
  25.         res = check_ZOC_B(civ,x,y); //check blocking unit. If civ == player_civ - draw it and draw terrain and city in its square.
  26.     else
  27.         res = 0; //unit can always go from and to the city
  28.     return res;
  29. }
  30.  
  31. get_city_area_civ(x,y)
  32. {
  33.     return (current_terrain_value[x][y]&7);
  34.     //returns 0..7 (city civ) for 21 squares of city area
  35.     //but what about other squares?
  36.     //if it's similar to save file (see current terrain value in JCivED), then...
  37.     //8 for +1 radius line around a city area -> returns 0 - it's ok...
  38.     //but if there's no city nearby then current land value can be 0 or 9..15
  39.     //problem here: what about 9..15 land value outside city areas?
  40.     //it will return current_terrain_value[x][y]-8 instead of civ number. But m.b. this is ok...
  41. }
  42.  
  43. barbarian_unit_ai_func(civ, unit_id) //civ == 0
  44. {
  45.     unit = get_unit_type(civ,unit_id); //legion, cavalry, diplomat etc.
  46.     x = get_unit_x(civ,unit_id);
  47.     y = get_unit_y(civ,unit_id);
  48.     if (y < 2 || y > 47)
  49.     {
  50.         unkn_var = disband_unit(param_civ,unit_id); //it returns void! it never returns anything anywhere but here!
  51.         return unkn_var; //?
  52.     }
  53.    
  54.     zoc_here = check_ZOC(civ,x,y); //1 if any adjacent enemy units (not in ocean...). If city - then always 0 (you can always go in and from a city ignoring ZoC...)
  55.     //zone of control in current square. If zoc_here == 1 && zoc_next == 1 -> no go
  56.    
  57.     if (get_unit_role(unit) == UR_TRANSPORT)
  58.     {
  59.         if (next_unit_in_stack != -1) //has passengers
  60.         {
  61.             city = find_closest_city(x,y); //return city id and set global var: gl_distance
  62.             dist_closest_city = gl_distance;
  63.             for (dir = 1; dir < 9; dir++)
  64.             {
  65.                 x2 = normalize(x+change_x[dir]); //the world is round. For example, x = -1 -> x = 79
  66.                 y2 = y+change_y[dir];
  67.                 terr = get_terrain(x2,y2);
  68.                 impr = get_improvements(x2,y2);
  69.                 if (dist_closest_city < 9 && terr != SQ_OCEAN
  70.                 && (impr&IM_CITY) == 0 //there's no city in this square
  71.                 && civ_id_of_unit_in_xy(x2,y2) == -1 //no units by any civ in this square
  72.                 && y2 > 1 && y2 < 48)
  73.                 {
  74.                     if (map_of_explored_terrain[x][y] & (1<<player_civ)) != 0 //square is explored by player civ
  75.                     && get_city_civ(city) == player_civ)
  76.                     {
  77.                         cont1 = get_continent(city_x[city],city_y[city]);
  78.                         cont2 = get_continent(x2,y2);
  79.                         if (cont1 == cont2)
  80.                         {
  81.                             unit_visibility |= (1<<player_civ); //set visibility bit of player civ to 1
  82.                            
  83.                             //fix view position? (if incorrect??) and change view position to x-8,y-6
  84.                            
  85.                             gl_message_type = 3; //Military Advisor:
  86.                             //message about landing...
  87.                         }
  88.                     }
  89.                     unit_visibility |= get_terrain_visibility(x,y);
  90.                     unit_remaining_moves = 0;
  91.                     return 0x75; //'u'->unload
  92.                 }
  93.                 if (civ_id_of_unit_in_xy(x2,y2) > 0) //somebody is next to us and it's not a barbarian
  94.                     return dir; //direction of movement/attack
  95.             } //for: all 8 directions
  96.             if (goto_x != -1) //boat is already in GoTo state
  97.                 return 0;
  98.         } //transport has passengers
  99.         best_city = 0;
  100.         cit_count = 0;
  101.         best_val; //best_val value was undefined?
  102.         do
  103.         {
  104.             if (city_flags[cit_count] != -1) //city exists
  105.             {
  106.                 distance = find_distance(x,y,city_x[cit_count],city_y[cit_count]);
  107.                 city_val = get_city_gold_loot(cit_count); // city_population*civ_treasure/(civ_population+1)
  108.                 city_val = (city_val+50)/(distance+1); //formula for target city
  109.                 if (city_val > best_val)
  110.                 {
  111.                     best_city = cit_count;
  112.                     best_val = city_val;
  113.                 }
  114.             }
  115.             cit_count++;
  116.         }
  117.         while (cit_count < 128);
  118.         if (best_city != 0)
  119.         {
  120.             goto_x = city_x[cit_count];
  121.             goto_y = city_y[cit_count];
  122.             return 0;
  123.         }
  124.         goto LABEL_DISBAND;
  125.     } //unit role: transport
  126.    
  127.     city = find_closest_city(x,y); //it sets global var: gl_distance
  128.     dist_closest_city = gl_distance;
  129.     cit_civ = get_city_civ(city);
  130.     if (dist_closest_city == 0 && (next_unit_in_stack == -1 || get_unit_role(unit) == UR_DEFENCE))
  131.         return 0x66; //'f' -> fortify
  132.        
  133.     x_direction_to_city = -2;
  134.     y_direction_to_city = -2;
  135.     if ((game_turn+unit_id)&3 == 0)
  136.     {
  137.         cont1 = get_continent(x,y);
  138.         cont2 = get_continent(city_x[city], city_y[city]);
  139.         if ((cont1 != cont2) || dist_closest_city > 8)
  140.         {
  141.             goto LABEL_DISBAND;
  142.         }
  143.     }
  144.     if (city != -1) //at least 1 city exists in the world
  145.     {
  146.         cont1 = get_continent(x,y);
  147.         cont2 = get_continent(city_x[city], city_y[city]);
  148.         if (cont1 == cont2
  149.         && (human_civ_bits & (1<<cit_civ)) != 0) //this is a human player's city... human_civ_bits and player_civ are different variables. Human civ bits are bit flags.
  150.         {
  151.             x_direction_to_city = get_sign(city_x[city] - x); //-1 if < 0 0 if 0 +1 if > 0
  152.             y_direction_to_city = get_sign(city_y[city] - y);
  153.         }
  154.     }
  155.     if (cit_civ == civ //barbarian city
  156.     || (civ_cities_total[cit_civ] < 2 && gold[cit_civ] < 100)) //or city owner has only 1 city and less than 100$
  157.     {
  158.         x_direction_to_city = -2;
  159.         y_direction_to_city = -2;
  160.     }
  161.     if (x_direction_to_city != -2)
  162.     {
  163.         //go straight to the city!
  164.         goto_x = city_x[city];
  165.         goto_y = city_y[city];
  166.         goto_dir = moveUnitGoto(civ,unit_id); //returns direction of next move: 1..9 //Unknown9 field in JCivED.
  167.         //moveUnitGoto was disassembled by darkpanda. You can find it somewhere on the forums...
  168.     }
  169.     goto_x = -1; //GoTo off. Barbarian units don't check it anywhere anyway and boat routine never go here, so it's kinda pointless?..
  170.     if (unit == U_DIPLOMAT)
  171.     {
  172.         terr = get_terrain(x,y);
  173.         if (next_unit_in_stack != -1 && terr != SQ_OCEAN && get_unit_type(civ,next_unit_in_stack) != U_DIPLOMAT) //if our diplomat's on land and some other barbarian unit's here and it's not an another diplomat
  174.         {
  175.             return 0x20; //space -> skip turn
  176.         }
  177.        
  178.         if (terr == SQ_OCEAN)
  179.         {
  180.             if (dist_closest_city > 2)
  181.                 goto LABEL_NOT_DIPLOMAT;
  182.         }
  183.         else
  184.         {
  185.             unit_id2 = find_my_closest_unit_id(civ,unit_id,x,y); //set gl_distance
  186.             dist_closest_unit = gl_distance;
  187.             if (dist_closest_unit < 4 && get_unit_type(civ,unit_id2) != U_DIPLOMAT)
  188.             {
  189.                 goto_x = get_unit_x(civ,unit_id2);
  190.                 goto_y = get_unit_y(civ,unit_id2);
  191.                 return 0; //do nothing?
  192.             }
  193.             if ((game_turn&7)+4 > dist_closest_city) //if remainder of dividing game_turn by 8 +4 > dist_closest_city
  194.                 goto LABEL_NOT_DIPLOMAT;
  195.         }
  196.         LABEL_DISBAND:
  197.         disband_unit(civ,unit_id);
  198.     }
  199.     else
  200.     {
  201.         LABEL_NOT_DIPLOMAT:
  202.         best_direction = 0;
  203.         best_val = -999;
  204.         dir = 1;
  205.         while (dir < 9)
  206.         {
  207.             x2 = normalize(x+change_x[dir]);
  208.             y2 = y+change_y[dir];
  209.             terr = get_terrain(x2,y2);
  210.            
  211.             if (((get_unit_domain(unit) == UD_FLEET) == (terr == SQ_OCEAN)) //if boat and in ocean OR not a boat and on land
  212.             && check_if_xy_within_the_map(x2,y2)) //X:0-79,Y:0-49 returns 0 if not
  213.             {
  214.                 unit_id2 = get_unit_id_in_xy(x2,y2); //returns -1 if no units here. Sets gl_unit_civ if some unit is here.
  215.                 if (get_unit_type(civ, unit_id) == U_DIPLOMAT)
  216.                 {
  217.                     curr_val = 0;
  218.                     if (unit_id2 != -1)
  219.                     {
  220.                         if (civ == gl_unit_civ) //it's a barbarian unit
  221.                         {
  222.                             curr_val = 99;
  223.                         }
  224.                         else //it's an enemy unit
  225.                         {
  226.                             curr_val = -99;
  227.                         }
  228.                     }
  229.                     find_closest_city(x2,y2); //set gl_distance
  230.                     dist_closest_city = gl_distance;
  231.                     rand = random(4); //0..3
  232.                     curr_val += dist_closest_city*4+rand+get_terrain_movement_cost(terr); //1 for grassland etc, 2 for hills etc, 3 for mountains
  233.                     LABEL_SET_BEST_VALUE:
  234.                     if (curr_val > best_val)
  235.                     {
  236.                         best_val = curr_val;
  237.                         best_direction = dir;
  238.                     }
  239.                 } //if diplomat
  240.                 else
  241.                 {
  242.                     impr = get_improvements(x2,y2);
  243.                     if ((impr&IM_CITY) == 0) //no city in square
  244.                     || get_city_area_civ(x2,y2) == 0) //or it's a barbarian city
  245.                     {
  246.                         impr = get_improvements(x2,y2); //yep, again...
  247.                         if ((impr&IM_IRRIGATION)==0 && (impr&IM_MINE)==0) //no irrigation and no mines here
  248.                             var_C = 0;
  249.                         else
  250.                             var_C = 6; //do want!
  251.                            
  252.                         if (get_city_area_civ(x2,y2) == 0)
  253.                             var_D = 0;
  254.                         else
  255.                             var_D = 4;  //city area or good terrain - do want!
  256.                             //not too sure if it actually returns non-zero value for good terrain outside of city area...
  257.                            
  258.                         curr_val = var_C+var_D+random(6);
  259.                         if (unit_id2 == -1) //no units in this direction
  260.                         {
  261.                             LABEL_REPEATED_PART:
  262.                             if (zoc_here == 0 //this square is free from enemy adjacent units (not in ocean) or there's a city here
  263.                             || get_unit_domain(unit) != UD_LAND //sea and air units ignore zones of control
  264.                             || unit_id2 != -1 //you can always move to square with other unit of your civ. Or you can attack enemy unit?..
  265.                             || check_ZOC(civ,x2,y2) == 0) //the next square is free from enemy adjacent units
  266.                             {
  267.                                 if (goto_dir == dir) //we are already going in this direction
  268.                                     curr_val += 6;
  269.                                 if (change_x[dir] == x_direction_to_city)
  270.                                     curr_val += 2;
  271.                                 if (change_y[dir] == y_direction_to_city)
  272.                                     curr_val += 2;
  273.                             }
  274.                             goto LABEL_SET_BEST_VALUE;
  275.                         }
  276.                         else //some units in this direciton
  277.                         {
  278.                             if (civ == gl_unit_civ) //it's a barbarian unit
  279.                             {
  280.                                 terr = get_terrain(x,y);
  281.                                 if (terr == SQ_OCEAN)
  282.                                 {
  283.                                     curr_val -= 20;
  284.                                     goto LABEL_REPEATED_PART;
  285.                                 }
  286.                             }
  287.                             else //it's an enemy
  288.                             {
  289.                                 terr = get_terrain(x,y);
  290.                                 if (terr != SQ_OCEAN)
  291.                                 {
  292.                                     if (get_unit_type(gl_unit2) != U_DIPLOMAT)
  293.                                         curr_val += 99;
  294.                                     goto LABEL_REPEATED_PART;
  295.                                 }
  296.                             }
  297.                         }
  298.                     } //no city in x2,y2 or it's a barbarian city
  299.                     else //there's a city in the next square
  300.                     {
  301.                         terr = get_terrain(x,y);
  302.                         if (terr != SQ_OCEAN)
  303.                             return dir; //direction of movement/attack
  304.                     }
  305.                 }
  306.             }
  307.             dir++;
  308.         } //while - check 8 adj. squares...
  309.         impr = get_improvements(x,y);
  310.         if ((impr&IM_CITY) == 0 || next_unit_in_stack != -1 || best_val >= 99)
  311.         {
  312.             goto_dir = best_direction;
  313.             return best_direction; //direction of movement/attack
  314.         }
  315.     } //not diplomat
  316.     return 0x20; //space->skip turn
  317. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement