| 207 | } |
| 208 | |
| 209 | void set_farms(color_ostream& out, const std::set<int>& plants, const std::vector<df::building_farmplotst*>& farms) |
| 210 | { |
| 211 | // this algorithm attempts to change as few farms as possible, while ensuring that |
| 212 | // the number of farms planting each eligible plant is "as equal as possible" |
| 213 | |
| 214 | int season = *df::global::cur_season; |
| 215 | |
| 216 | if (farms.empty() || plants.empty()) |
| 217 | { |
| 218 | // if no more plants were requested, fallow all farms |
| 219 | // if there were no farms, do nothing |
| 220 | for (auto farm : farms) |
| 221 | { |
| 222 | set_farm(out, -1, farm, season); |
| 223 | } |
| 224 | return; |
| 225 | } |
| 226 | |
| 227 | int min = farms.size() / plants.size(); // the number of farms that should plant each eligible plant, rounded down |
| 228 | int extra = farms.size() - min * plants.size(); // the remainder that cannot be evenly divided |
| 229 | |
| 230 | std::map<int, int> counters; |
| 231 | std::queue<df::building_farmplotst*> toChange; |
| 232 | |
| 233 | for (auto farm : farms) |
| 234 | { |
| 235 | int o = farm->plant_id[season]; |
| 236 | if (plants.count(o) == 0 || counters[o] > min || (counters[o] == min && extra == 0)) |
| 237 | toChange.push(farm); // this farm is an excess instance for the plant it is currently planting |
| 238 | else |
| 239 | { |
| 240 | if (counters[o] == min) |
| 241 | extra--; // allocate off one of the remainder farms |
| 242 | counters[o]++; |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | for (auto n : plants) |
| 247 | { |
| 248 | int c = counters[n]; |
| 249 | while (toChange.size() > 0 && (c < min || (c == min && extra > 0))) |
| 250 | { |
| 251 | // pick one of the excess farms and change it to plant this plant |
| 252 | df::building_farmplotst* farm = toChange.front(); |
| 253 | set_farm(out, n, farm, season); |
| 254 | toChange.pop(); |
| 255 | if (c++ == min) |
| 256 | extra--; |
| 257 | } |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | void process(color_ostream& out) |
| 262 | { |