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