001package com.fs.starfarer.api.impl.campaign.procgen; 002 003import java.util.Collection; 004import java.util.HashSet; 005import java.util.Set; 006 007import com.fs.starfarer.api.Global; 008import com.fs.starfarer.api.impl.campaign.procgen.MarkovNames.MarkovNameResult; 009import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator.LagrangePointType; 010import com.fs.starfarer.api.util.WeightedRandomPicker; 011 012public class ProcgenUsedNames { 013 014 public static class NamePick { 015 public NameGenData spec; 016 public String nameWithRomanSuffixIfAny; 017 public String secondaryWithRomanSuffixIfAny; 018 public NamePick(NameGenData spec, String nameWithRomanSuffixIfAny, String secondaryWithRomanSuffixIfAny) { 019 this.spec = spec; 020 this.nameWithRomanSuffixIfAny = nameWithRomanSuffixIfAny; 021 this.secondaryWithRomanSuffixIfAny = secondaryWithRomanSuffixIfAny; 022 } 023 024 } 025 026 public static final String KEY = "ProcgenUsedNames_key"; 027 private Set<String> names = new HashSet<String>(); 028 029 public static void notifyUsed(String name) { 030 getUsed().names.add(name); 031 } 032 033 public static boolean isUsed(String name) { 034 return getUsed().names.contains(name); 035 } 036 037 public static ProcgenUsedNames getUsed() { //for (String name : ((ProcgenUsedNames) test).names) System.out.println(name); 038 Object test = Global.getSector().getPersistentData().get(KEY); 039 if (test == null) { 040 test = new ProcgenUsedNames(); 041 Global.getSector().getPersistentData().put(KEY, test); 042 } 043 return (ProcgenUsedNames) test; 044 } 045 046 047 public static NamePick pickName(String tag, String parent, LagrangePointType lagrangePoint) { 048 WeightedRandomPicker<NamePick> picker = new WeightedRandomPicker<NamePick>(StarSystemGenerator.random); 049 050 051 Collection<NameGenData> all = Global.getSettings().getAllSpecs(NameGenData.class); 052 053 // names for child of parent, if any 054 if (parent != null) { 055 for (NameGenData spec : all) { 056 if (isUsed(spec.getName())) continue; 057 if (!spec.hasTag(tag)) continue; 058 if (parent == null && spec.getName().contains("$parent")) continue; 059 if (spec.hasParent(parent)) { 060 picker.add(new NamePick(spec, spec.getName(), spec.getSecondary()), spec.getFrequency()); 061 } 062 } 063 } 064 065 // if needed, add names w/o parent 066 if (picker.isEmpty()) { 067 for (NameGenData spec : all) { 068 if (isUsed(spec.getName())) continue; 069 if (!spec.hasTag(tag)) continue; 070 if (!spec.getParents().isEmpty()) continue; 071 if (parent == null && spec.getName().contains("$parent")) continue; 072 picker.add(new NamePick(spec, spec.getName(), spec.getSecondary()), spec.getFrequency()); 073 } 074 } 075 076 // if there's nothing, try to create a name using markov chains 077 // before moving on to roman numerals 078 if (picker.isEmpty()) { 079 int attempts = 10; 080 for (int i = 0; i < attempts; i++) { 081 MarkovNameResult name = MarkovNames.generate(picker.getRandom()); 082 if (name == null || name.name == null) continue; 083 if (isUsed(name.name)) continue; 084 085 NameGenData data = new NameGenData(name.name, null); 086 NamePick pick = new NamePick(data, name.name, null); 087 return pick; 088 } 089 } 090 091 092 093 // if still no names, we're out of names. start adding roman numerals. 094 // (or there's nothing at all for the tag, but that's a bug elsewhere) 095 if (picker.isEmpty()) { 096 OUTER: for (Object obj : all) { 097 NameGenData spec = (NameGenData) obj; 098 if (!spec.hasTag(tag)) continue; 099 100 String base = spec.getName(); 101 for (int i = 2; i < 4000; i++) { 102 String name = base + " " + Global.getSettings().getRoman(i); 103 if (isUsed(name)) continue; 104 if (parent == null && spec.getName().contains("$parent")) continue; 105 106 String secondary = null; 107 if (spec.getSecondary() != null) { 108 secondary = spec.getSecondary() + " " + Global.getSettings().getRoman(i); 109 } 110 picker.add(new NamePick(spec, name, secondary), (4000f - i) * spec.getFrequency()); // lower numbers more likely to be picked 111 continue OUTER; 112 } 113 } 114 } 115 116 NamePick pick = picker.pick(); 117 118 if (pick != null) { 119 pick.nameWithRomanSuffixIfAny = doTokenReplacement(pick.nameWithRomanSuffixIfAny, parent, lagrangePoint); 120 if (pick.secondaryWithRomanSuffixIfAny != null) { 121 pick.secondaryWithRomanSuffixIfAny = doTokenReplacement(pick.secondaryWithRomanSuffixIfAny, parent, lagrangePoint); 122 } 123 124 } 125 126 return pick; 127 } 128 129 public static String doTokenReplacement(String name, String parent, LagrangePointType lagrange) { 130 if (parent != null) { 131 name = name.replaceAll("\\$parent", parent); 132 name = name.replaceAll("s's", "s'"); 133 } 134 if (lagrange != null) { 135 name = name.replaceAll("\\$L", lagrange.name()); 136 } else { 137 name = name.replaceAll("\\$L ", ""); 138 } 139 return name; 140 } 141} 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176