9 package micropolisj.engine;
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
15 import java.util.Properties;
30 BuildingInfo buildingInfo;
34 Map<String, String> attributes;
40 this.tileNumber = tileNumber;
41 this.attributes =
new HashMap<String, String>();
42 this.images =
new ArrayList<String>();
45 public static TileSpec parse(
int tileNumber, String inStr, Properties tilesRc) {
47 ts.
load(inStr, tilesRc);
52 return attributes.get(key);
57 return (v != null && v.equals(
"true"));
60 public static class BuildingInfo {
77 BuildingInfo bi =
new BuildingInfo();
79 String[] p2 = tmp.split(
"x");
80 bi.width = Integer.parseInt(p2[0]);
81 bi.height = Integer.parseInt(p2[1]);
83 bi.members =
new short[bi.width * bi.height];
84 int startTile = tileNumber;
89 startTile -= bi.width;
92 for(
int row = 0; row < bi.height; row++) {
93 for(
int col = 0; col < bi.width; col++) {
94 bi.members[row * bi.width + col] = (short) startTile;
99 this.buildingInfo = bi;
103 if(buildingInfo != null) {
104 return new CityDimension(buildingInfo.width, buildingInfo.height);
113 if(v != null && v.startsWith(
"#")) {
114 return Integer.parseInt(v.substring(1));
123 return images.toArray(
new String[0]);
137 else if(
owner != null) {
149 return Integer.parseInt(v);
156 protected void load(String inStr, Properties tilesRc) {
157 Scanner in =
new Scanner(inStr);
159 while(in.hasMore()) {
161 if(in.peekChar() ==
'(') {
163 String k = in.readAttributeKey();
165 if(in.peekChar() ==
'=') {
167 v = in.readAttributeValue();
171 if(!attributes.containsKey(k)) {
172 attributes.put(k, v);
173 String sup = tilesRc.getProperty(k);
179 attributes.put(k, v);
183 else if(in.peekChar() ==
'|' || in.peekChar() ==
',') {
184 in.eatChar(in.peekChar());
188 String v = in.readImageSpec();
200 static class Scanner {
204 Scanner(String str) {
208 private void skipWhitespace() {
209 while(off < str.length() && Character.isWhitespace(str.charAt(off))) {
214 public int peekChar() {
216 if(off < str.length()) {
217 return str.charAt(off);
224 public void eatChar(
int ch) {
226 assert str.charAt(off) == ch;
230 public String readAttributeKey() {
234 while(off < str.length() && (str.charAt(off) ==
'-' || Character.isLetterOrDigit(str.charAt(off)))) {
239 return str.substring(start, off);
246 public String readAttributeValue() {
250 public String readImageSpec() {
254 protected String readString() {
258 if(peekChar() ==
'"') {
264 while(off < str.length()) {
265 int c = str.charAt(off);
269 return str.substring(start, end);
271 else if(endQuote == 0 && (Character.isWhitespace(c) || c ==
')' || c ==
'|')) {
273 return str.substring(start, end);
277 return str.substring(start);
280 public boolean hasMore() {
281 return peekChar() != -1;
286 return "{tile#" + tileNumber +
"}";
289 void resolveReferences(Map<String, TileSpec> tileMap) {
292 this.animNext = tileMap.get(tmp);
296 this.onPower = tileMap.get(tmp);
300 this.onShutdown = tileMap.get(tmp);
311 String[] parts = text.split(
",");
312 if(parts.length != 3) {
313 throw new Error(
"Invalid building-part specification");
316 this.
owner = tileMap.get(parts[0]);
320 assert this.
owner != null;
325 int ntiles = recipe.size();
326 String[] tileNames =
new String[ntiles];
328 for(
int i = 0; recipe.containsKey(Integer.toString(i)); i++) {
329 tileNames[ntiles++] = Integer.toString(i);
331 int naturalNumberTiles = ntiles;
333 for(Object n_obj : recipe.keySet()) {
334 String n = (String) n_obj;
335 if(n.matches(
"^\\d+$")) {
336 int x = Integer.parseInt(n);
337 if(x >= 0 && x < naturalNumberTiles) {
338 assert tileNames[x].equals(n);
342 assert ntiles < tileNames.length;
343 tileNames[ntiles++] = n;
345 assert ntiles == tileNames.length;