static Table<Campaign::SiteInfo> getTerrain(RandomGen& random, Vec2 size, int numBlocked) { Table<Campaign::SiteInfo> ret(size, {}); for (Vec2 v : ret.getBounds()) ret[v].viewId.push_back(ViewId("grass")); vector<Vec2> freePos = ret.getBounds().getAllSquares(); for (int i : Range(numBlocked)) { Vec2 pos = random.choose(freePos); freePos.removeElement(pos); ret[pos].setBlocked(); } return ret; }
optional<Campaign> Campaign::prepareCampaign(View* view, Options* options, RetiredGames&& retired, RandomGen& random) { Vec2 size(16, 9); int numBlocked = 0.6 * size.x * size.y; Table<SiteInfo> terrain = getTerrain(random, size, numBlocked); string worldName = NameGenerator::get(NameGeneratorId::WORLD)->getNext(); options->setDefaultString(OptionId::KEEPER_NAME, NameGenerator::get(NameGeneratorId::FIRST)->getNext()); while (1) { //options->setLimits(OptionId::RETIRED_VILLAINS, 0, min<int>(retired.size(), 4)); options->setLimits(OptionId::MAIN_VILLAINS, 0, 9); options->setLimits(OptionId::LESSER_VILLAINS, 0, 8); options->setLimits(OptionId::ALLIES, 0, 6); options->setLimits(OptionId::INFLUENCE_SIZE, 3, 6); int numRetired = min(retired.getNumActive(), options->getIntValue(OptionId::MAIN_VILLAINS)); int numMain = options->getIntValue(OptionId::MAIN_VILLAINS) - numRetired; int numLesser = options->getIntValue(OptionId::LESSER_VILLAINS); int numAllies = options->getIntValue(OptionId::ALLIES); vector<VillainInfo> mainVillains; while (mainVillains.size() < numMain) append(mainVillains, random.permutation(getMainVillains())); mainVillains.resize(numMain); vector<VillainInfo> lesserVillains; while (lesserVillains.size() < numLesser) append(lesserVillains, random.permutation(getLesserVillains())); lesserVillains.resize(numLesser); vector<VillainInfo> allies; while (allies.size() < numAllies) append(allies, random.permutation(getAllies())); allies.resize(numAllies); Campaign campaign(terrain); campaign.worldName = worldName; vector<Vec2> freePos; for (Vec2 v : Rectangle(size)) if (campaign.sites[v].canEmbark()) freePos.push_back(v); for (int i : All(mainVillains)) { Vec2 pos = random.choose(freePos); removeElement(freePos, pos); campaign.sites[pos].dweller = mainVillains[i]; } vector<RetiredGames::RetiredGame> activeGames = retired.getActiveGames(); for (int i : Range(numRetired)) { Vec2 pos = random.choose(freePos); removeElement(freePos, pos); campaign.sites[pos].dweller = RetiredInfo{activeGames[i].gameInfo, activeGames[i].fileInfo}; } for (int i : All(lesserVillains)) { Vec2 pos = random.choose(freePos); removeElement(freePos, pos); campaign.sites[pos].dweller = lesserVillains[i]; } for (int i : All(allies)) { Vec2 pos = random.choose(freePos); removeElement(freePos, pos); campaign.sites[pos].dweller = allies[i]; } while (1) { bool updateMap = false; campaign.influenceSize = options->getIntValue(OptionId::INFLUENCE_SIZE); campaign.refreshInfluencePos(); CampaignAction action = view->prepareCampaign(campaign, options, retired); switch (action.getId()) { case CampaignActionId::REROLL_MAP: terrain = getTerrain(random, size, numBlocked); worldName = NameGenerator::get(NameGeneratorId::WORLD)->getNext(); options->setDefaultString(OptionId::KEEPER_NAME, NameGenerator::get(NameGeneratorId::FIRST)->getNext()); case CampaignActionId::UPDATE_MAP: updateMap = true; break; case CampaignActionId::UPDATE_OPTION: switch (action.get<OptionId>()) { case OptionId::KEEPER_NAME: case OptionId::INFLUENCE_SIZE: break; default: updateMap = true; break; } break; case CampaignActionId::CANCEL: return none; case CampaignActionId::CHOOSE_SITE: if (campaign.playerPos) campaign.clearSite(*campaign.playerPos); campaign.playerPos = action.get<Vec2>(); campaign.sites[*campaign.playerPos].dweller = PlayerInfo{ViewId::KEEPER}; break; case CampaignActionId::CONFIRM: return campaign; } if (updateMap) break; } } }