1/* 2 * Copyright (C) 2010-2013 Robert Ancell 3 * 4 * This program is free software: you can redistribute it and/or modify it under 5 * the terms of the GNU General Public License as published by the Free Software 6 * Foundation, either version 2 of the License, or (at your option) any later 7 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the 8 * license. 9 */ 10 11public class Slot : Object 12{ 13 public int x; 14 public int y; 15 public int layer; 16 17 public Slot (int x, int y, int layer) 18 { 19 this.x = x; 20 this.y = y; 21 this.layer = layer; 22 } 23} 24 25private static int compare_slots (Slot a, Slot b) 26{ 27 /* Sort lowest to highest */ 28 var dl = a.layer - b.layer; 29 if (dl != 0) 30 return dl; 31 32 /* Sort diagonally, top left to bottom right */ 33 var dx = a.x - b.x; 34 var dy = a.y - b.y; 35 if (dx > dy) 36 return -1; 37 if (dx < dy) 38 return 1; 39 40 return 0; 41} 42 43public class Map : Object 44{ 45 public string? name = null; 46 public string? score_name = null; 47 public List<Slot> slots = null; 48 49 public Map.test () 50 { 51 name = "Test"; 52 score_name = "test"; 53 slots.append (new Slot (0, 0, 0)); 54 slots.append (new Slot (2, 0, 0)); 55 slots.append (new Slot (2, 0, 1)); 56 slots.append (new Slot (4, 0, 0)); 57 slots.append (new Slot (0, 2, 0)); 58 slots.append (new Slot (2, 2, 0)); 59 slots.append (new Slot (2, 2, 1)); 60 slots.append (new Slot (4, 2, 0)); 61 } 62 63 public Map.builtin () 64 { 65 name = "Easy"; 66 score_name = "easy"; 67 slots.append (new Slot (13, 7, 4)); 68 slots.append (new Slot (12, 8, 3)); 69 slots.append (new Slot (14, 8, 3)); 70 slots.append (new Slot (12, 6, 3)); 71 slots.append (new Slot (14, 6, 3)); 72 slots.append (new Slot (10, 10, 2)); 73 slots.append (new Slot (12, 10, 2)); 74 slots.append (new Slot (14, 10, 2)); 75 slots.append (new Slot (16, 10, 2)); 76 slots.append (new Slot (10, 8, 2)); 77 slots.append (new Slot (12, 8, 2)); 78 slots.append (new Slot (14, 8, 2)); 79 slots.append (new Slot (16, 8, 2)); 80 slots.append (new Slot (10, 6, 2)); 81 slots.append (new Slot (12, 6, 2)); 82 slots.append (new Slot (14, 6, 2)); 83 slots.append (new Slot (16, 6, 2)); 84 slots.append (new Slot (10, 4, 2)); 85 slots.append (new Slot (12, 4, 2)); 86 slots.append (new Slot (14, 4, 2)); 87 slots.append (new Slot (16, 4, 2)); 88 slots.append (new Slot (8, 12, 1)); 89 slots.append (new Slot (10, 12, 1)); 90 slots.append (new Slot (12, 12, 1)); 91 slots.append (new Slot (14, 12, 1)); 92 slots.append (new Slot (16, 12, 1)); 93 slots.append (new Slot (18, 12, 1)); 94 slots.append (new Slot (8, 10, 1)); 95 slots.append (new Slot (10, 10, 1)); 96 slots.append (new Slot (12, 10, 1)); 97 slots.append (new Slot (14, 10, 1)); 98 slots.append (new Slot (16, 10, 1)); 99 slots.append (new Slot (18, 10, 1)); 100 slots.append (new Slot (8, 8, 1)); 101 slots.append (new Slot (10, 8, 1)); 102 slots.append (new Slot (12, 8, 1)); 103 slots.append (new Slot (14, 8, 1)); 104 slots.append (new Slot (16, 8, 1)); 105 slots.append (new Slot (18, 8, 1)); 106 slots.append (new Slot (8, 6, 1)); 107 slots.append (new Slot (10, 6, 1)); 108 slots.append (new Slot (12, 6, 1)); 109 slots.append (new Slot (14, 6, 1)); 110 slots.append (new Slot (16, 6, 1)); 111 slots.append (new Slot (18, 6, 1)); 112 slots.append (new Slot (8, 4, 1)); 113 slots.append (new Slot (10, 4, 1)); 114 slots.append (new Slot (12, 4, 1)); 115 slots.append (new Slot (14, 4, 1)); 116 slots.append (new Slot (16, 4, 1)); 117 slots.append (new Slot (18, 4, 1)); 118 slots.append (new Slot (8, 2, 1)); 119 slots.append (new Slot (10, 2, 1)); 120 slots.append (new Slot (12, 2, 1)); 121 slots.append (new Slot (14, 2, 1)); 122 slots.append (new Slot (16, 2, 1)); 123 slots.append (new Slot (18, 2, 1)); 124 slots.append (new Slot (2, 14, 0)); 125 slots.append (new Slot (4, 14, 0)); 126 slots.append (new Slot (6, 14, 0)); 127 slots.append (new Slot (8, 14, 0)); 128 slots.append (new Slot (10, 14, 0)); 129 slots.append (new Slot (12, 14, 0)); 130 slots.append (new Slot (14, 14, 0)); 131 slots.append (new Slot (16, 14, 0)); 132 slots.append (new Slot (18, 14, 0)); 133 slots.append (new Slot (20, 14, 0)); 134 slots.append (new Slot (22, 14, 0)); 135 slots.append (new Slot (24, 14, 0)); 136 slots.append (new Slot (6, 12, 0)); 137 slots.append (new Slot (8, 12, 0)); 138 slots.append (new Slot (10, 12, 0)); 139 slots.append (new Slot (12, 12, 0)); 140 slots.append (new Slot (14, 12, 0)); 141 slots.append (new Slot (16, 12, 0)); 142 slots.append (new Slot (18, 12, 0)); 143 slots.append (new Slot (20, 12, 0)); 144 slots.append (new Slot (4, 10, 0)); 145 slots.append (new Slot (6, 10, 0)); 146 slots.append (new Slot (8, 10, 0)); 147 slots.append (new Slot (10, 10, 0)); 148 slots.append (new Slot (12, 10, 0)); 149 slots.append (new Slot (14, 10, 0)); 150 slots.append (new Slot (16, 10, 0)); 151 slots.append (new Slot (18, 10, 0)); 152 slots.append (new Slot (20, 10, 0)); 153 slots.append (new Slot (22, 10, 0)); 154 slots.append (new Slot (0, 7, 0)); 155 slots.append (new Slot (2, 8, 0)); 156 slots.append (new Slot (4, 8, 0)); 157 slots.append (new Slot (6, 8, 0)); 158 slots.append (new Slot (8, 8, 0)); 159 slots.append (new Slot (10, 8, 0)); 160 slots.append (new Slot (12, 8, 0)); 161 slots.append (new Slot (14, 8, 0)); 162 slots.append (new Slot (16, 8, 0)); 163 slots.append (new Slot (18, 8, 0)); 164 slots.append (new Slot (20, 8, 0)); 165 slots.append (new Slot (22, 8, 0)); 166 slots.append (new Slot (24, 8, 0)); 167 slots.append (new Slot (2, 6, 0)); 168 slots.append (new Slot (4, 6, 0)); 169 slots.append (new Slot (6, 6, 0)); 170 slots.append (new Slot (8, 6, 0)); 171 slots.append (new Slot (10, 6, 0)); 172 slots.append (new Slot (12, 6, 0)); 173 slots.append (new Slot (14, 6, 0)); 174 slots.append (new Slot (16, 6, 0)); 175 slots.append (new Slot (18, 6, 0)); 176 slots.append (new Slot (20, 6, 0)); 177 slots.append (new Slot (22, 6, 0)); 178 slots.append (new Slot (24, 6, 0)); 179 slots.append (new Slot (4, 4, 0)); 180 slots.append (new Slot (6, 4, 0)); 181 slots.append (new Slot (8, 4, 0)); 182 slots.append (new Slot (10, 4, 0)); 183 slots.append (new Slot (12, 4, 0)); 184 slots.append (new Slot (14, 4, 0)); 185 slots.append (new Slot (16, 4, 0)); 186 slots.append (new Slot (18, 4, 0)); 187 slots.append (new Slot (20, 4, 0)); 188 slots.append (new Slot (22, 4, 0)); 189 slots.append (new Slot (6, 2, 0)); 190 slots.append (new Slot (8, 2, 0)); 191 slots.append (new Slot (10, 2, 0)); 192 slots.append (new Slot (12, 2, 0)); 193 slots.append (new Slot (14, 2, 0)); 194 slots.append (new Slot (16, 2, 0)); 195 slots.append (new Slot (18, 2, 0)); 196 slots.append (new Slot (20, 2, 0)); 197 slots.append (new Slot (2, 0, 0)); 198 slots.append (new Slot (4, 0, 0)); 199 slots.append (new Slot (6, 0, 0)); 200 slots.append (new Slot (8, 0, 0)); 201 slots.append (new Slot (10, 0, 0)); 202 slots.append (new Slot (12, 0, 0)); 203 slots.append (new Slot (14, 0, 0)); 204 slots.append (new Slot (16, 0, 0)); 205 slots.append (new Slot (18, 0, 0)); 206 slots.append (new Slot (20, 0, 0)); 207 slots.append (new Slot (22, 0, 0)); 208 slots.append (new Slot (24, 0, 0)); 209 slots.append (new Slot (26, 7, 0)); 210 slots.append (new Slot (28, 7, 0)); 211 } 212 213 public uint width 214 { 215 get 216 { 217 var w = 0; 218 foreach (var slot in slots) 219 { 220 if (slot.x > w) 221 w = slot.x; 222 } 223 224 /* Width is x location of right most tile and the width of that tile (2 units) */ 225 return w + 2; 226 } 227 } 228 229 public uint height 230 { 231 get 232 { 233 var h = 0; 234 foreach (var slot in slots) 235 { 236 if (slot.y > h) 237 h = slot.y; 238 } 239 240 /* Height is x location of bottom most tile and the height of that tile (2 units) */ 241 return h + 2; 242 } 243 } 244} 245 246public class MapLoader : Object 247{ 248 public List<Map> maps = null; 249 private Map map; 250 private int layer_z = 0; 251 252 public void load (string filename) throws Error 253 { 254 string data; 255 size_t length; 256 FileUtils.get_contents (filename, out data, out length); 257 258 var parser = MarkupParser (); 259 parser.start_element = start_element_cb; 260 parser.end_element = end_element_cb; 261 parser.text = null; 262 parser.passthrough = null; 263 parser.error = null; 264 var parse_context = new MarkupParseContext (parser, 0, this, null); 265 try 266 { 267 parse_context.parse (data, (ssize_t) length); 268 } 269 catch (MarkupError e) 270 { 271 } 272 } 273 274 private string? get_attribute (string[] attribute_names, string[] attribute_values, string name, string? default = null) 275 { 276 for (var i = 0; attribute_names[i] != null; i++) 277 { 278 if (attribute_names[i].down () == name) 279 return attribute_values[i]; 280 } 281 282 return default; 283 } 284 285 private double get_attribute_d (string[] attribute_names, string[] attribute_values, string name, double default = 0.0) 286 { 287 var a = get_attribute (attribute_names, attribute_values, name); 288 if (a == null) 289 return default; 290 else 291 return double.parse (a); 292 } 293 294 private void start_element_cb (MarkupParseContext context, string element_name, string[] attribute_names, string[] attribute_values) throws MarkupError 295 { 296 /* Identify the tag. */ 297 switch (element_name.down ()) 298 { 299 case "mahjongg": 300 break; 301 302 case "map": 303 map = new Map (); 304 map.name = get_attribute (attribute_names, attribute_values, "name", ""); 305 map.score_name = get_attribute (attribute_names, attribute_values, "scorename", ""); 306 break; 307 308 case "layer": 309 layer_z = (int) get_attribute_d (attribute_names, attribute_values, "z"); 310 break; 311 312 case "row": 313 var x1 = (int) (get_attribute_d (attribute_names, attribute_values, "left") * 2); 314 var x2 = (int) (get_attribute_d (attribute_names, attribute_values, "right") * 2); 315 var y = (int) (get_attribute_d (attribute_names, attribute_values, "y") * 2); 316 var z = (int) get_attribute_d (attribute_names, attribute_values, "z", layer_z); 317 for (; x1 <= x2; x1 += 2) 318 map.slots.append (new Slot (x1, y, z)); 319 break; 320 321 case "column": 322 var x = (int) (get_attribute_d (attribute_names, attribute_values, "x") * 2); 323 var y1 = (int) (get_attribute_d (attribute_names, attribute_values, "top") * 2); 324 var y2 = (int) (get_attribute_d (attribute_names, attribute_values, "bottom") * 2); 325 var z = (int) get_attribute_d (attribute_names, attribute_values, "z", layer_z); 326 for (; y1 <= y2; y1 += 2) 327 map.slots.append (new Slot (x, y1, z)); 328 break; 329 330 case "block": 331 var x1 = (int) (get_attribute_d (attribute_names, attribute_values, "left") * 2); 332 var x2 = (int) (get_attribute_d (attribute_names, attribute_values, "right") * 2); 333 var y1 = (int) (get_attribute_d (attribute_names, attribute_values, "top") * 2); 334 var y2 = (int) (get_attribute_d (attribute_names, attribute_values, "bottom") * 2); 335 var z = (int) get_attribute_d (attribute_names, attribute_values, "z", layer_z); 336 for (; x1 <= x2; x1 += 2) 337 for (var y = y1; y <= y2; y += 2) 338 map.slots.append (new Slot (x1, y, z)); 339 break; 340 341 case "tile": 342 var x = (int) (get_attribute_d (attribute_names, attribute_values, "x") * 2); 343 var y = (int) (get_attribute_d (attribute_names, attribute_values, "y") * 2); 344 var z = (int) get_attribute_d (attribute_names, attribute_values, "z", layer_z); 345 map.slots.append (new Slot (x, y, z)); 346 break; 347 } 348 } 349 350 private void end_element_cb (MarkupParseContext context, string element_name) throws MarkupError 351 { 352 switch (element_name.down ()) 353 { 354 case "map": 355 var n_slots = map.slots.length (); 356 if (map.name != null && map.score_name != null && n_slots <= 144 && n_slots % 2 == 0) 357 maps.append (map); 358 else 359 warning ("Invalid map"); 360 map = null; 361 break; 362 363 case "layer": 364 layer_z = 0; 365 break; 366 } 367 } 368} 369