/// <summary> /// Load a mock level. /// </summary> private void LoadMock() { BoardDimensions = new Point(4, 7); Board = new TileInfo[7, 4]; Board[0, 0] = new TileInfo(TileType.Outputter, false); Board[0, 0].SetAttr<Directions>(DIRECTION_ATTRIBUTE, Directions.Up); Board[0, 0].SetAttr<LaserColours>(COLOUR_ATTRIBUTE, LaserColours.Red); Board[0, 1] = new TileInfo(TileType.Outputter, false); Board[0, 1].SetAttr<Directions>(DIRECTION_ATTRIBUTE, Directions.Up); Board[0, 1].SetAttr<LaserColours>(COLOUR_ATTRIBUTE, LaserColours.Blue); Board[0, 2] = new TileInfo(TileType.Outputter, false); Board[0, 2].SetAttr<Directions>(DIRECTION_ATTRIBUTE, Directions.Up); Board[0, 2].SetAttr<LaserColours>(COLOUR_ATTRIBUTE, LaserColours.Green); Board[0, 3] = new TileInfo(TileType.Outputter, false); Board[0, 3].SetAttr<Directions>(DIRECTION_ATTRIBUTE, Directions.Up); Board[0, 3].SetAttr<LaserColours>(COLOUR_ATTRIBUTE, LaserColours.Purple); Board[1, 0] = new TileInfo(TileType.Empty, true); Board[1, 1] = new TileInfo(TileType.Empty, true); Board[1, 2] = new TileInfo(TileType.Empty, true); Board[1, 3] = new TileInfo(TileType.Empty, true); Board[2, 0] = new TileInfo(TileType.Empty, true); Board[2, 1] = new TileInfo(TileType.Empty, true); Board[2, 2] = new TileInfo(TileType.Empty, true); Board[2, 3] = new TileInfo(TileType.Empty, true); Board[3, 0] = new TileInfo(TileType.Empty, true); Board[3, 1] = new TileInfo(TileType.Empty, true); Board[3, 2] = new TileInfo(TileType.Empty, true); Board[3, 3] = new TileInfo(TileType.Empty, true); Board[4, 0] = new TileInfo(TileType.RF_ULxUR_U, false); Board[4, 1] = new TileInfo(TileType.RF_ULxUR_U, false); Board[4, 2] = new TileInfo(TileType.RF_ULxUR_U, false); Board[4, 3] = new TileInfo(TileType.RF_ULxUR_U, false); Board[5, 0] = new TileInfo(TileType.Empty, true); Board[5, 1] = new TileInfo(TileType.Empty, true); Board[5, 2] = new TileInfo(TileType.Empty, true); Board[5, 3] = new TileInfo(TileType.Empty, true); Board[6, 0] = new TileInfo(TileType.Receiver, false); Board[6, 0].SetAttr<Directions>(DIRECTION_ATTRIBUTE, Directions.Up); Board[6, 0].SetAttr<LaserColours>(COLOUR_ATTRIBUTE, LaserColours.Purple); Board[6, 1] = new TileInfo(TileType.Receiver, false); Board[6, 1].SetAttr<Directions>(DIRECTION_ATTRIBUTE, Directions.Up); Board[6, 1].SetAttr<LaserColours>(COLOUR_ATTRIBUTE, LaserColours.Red); Board[6, 2] = new TileInfo(TileType.Receiver, false); Board[6, 2].SetAttr<Directions>(DIRECTION_ATTRIBUTE, Directions.Up); Board[6, 2].SetAttr<LaserColours>(COLOUR_ATTRIBUTE, LaserColours.Green); Board[6, 3] = new TileInfo(TileType.Receiver, false); Board[6, 3].SetAttr<Directions>(DIRECTION_ATTRIBUTE, Directions.Up); Board[6, 3].SetAttr<LaserColours>(COLOUR_ATTRIBUTE, LaserColours.Blue); Outputters = new Point[] { new Point(0, 0), new Point(1, 0), new Point(2, 0), new Point(3, 0) }; Receivers = new Point[] { new Point(0, 6), new Point(1, 6), new Point(2, 6), new Point(3, 6) }; foreach (var row in InventoryTileOrder) foreach (var tileType in row) Inventory[tileType] = -1; }
/// <summary> /// Read a tile element. In this case, a tile element is any of "<Tile>", /// "<Outputter>", or "<Receiver>", where the string "type" parameter /// determines which of the three it is. /// </summary> private TileInfo ReadTileElement(XmlElement tile) { var tileName = tile.GetAttribute(TYPE_ATTRIBUTE); TileType tileType; var success = Enum.TryParse<TileType>(tileName, out tileType); if (!success) { Error_InvalidAttributeValue("tile type", tile.GetAttribute(TYPE_ATTRIBUTE)); } // All non-empty tiles initially specified in the level file are closed to // prevent the player overwriting them. var tileInfo = new TileInfo(tileType, false); foreach (var attr in tile.Attributes.Cast<XmlAttribute>()) { switch(attr.Name) { case DIRECTION_ATTRIBUTE: if (!Directions.DirectionsByName.ContainsKey(attr.InnerText)) Error_InvalidAttributeValue("direction", attr.InnerText); var direction = Directions.DirectionsByName[attr.InnerText]; tileInfo.SetAttr<Directions>(attr.Name, direction); break; case COLOUR_ATTRIBUTE: if (!LaserColours.ColoursByName.ContainsKey(attr.InnerText)) Error_InvalidAttributeValue("colour", attr.InnerText); var colour = LaserColours.ColoursByName[attr.InnerText]; tileInfo.SetAttr<LaserColours>(attr.Name, colour); break; default: break; } } // Check to ensure a tile of a specific type has the required // attributes. switch (tileType) { case TileType.Outputter: case TileType.Receiver: if (!tileInfo.HasAttr<LaserColours>(COLOUR_ATTRIBUTE) || !tileInfo.HasAttr<Directions>(DIRECTION_ATTRIBUTE)) Error_NoColourOrDirectionAttribute(tileName.ToLower()); break; case TileType.OpenReceiver: case TileType.OpenReceiver_pass_L: case TileType.OpenReceiver_pass_U: case TileType.OpenReceiver_pass_UL: case TileType.OpenReceiver_pass_UR: if (!tileInfo.HasAttr<LaserColours>(COLOUR_ATTRIBUTE)) Error_NoColourOrDirectionAttribute(tileName.ToLower()); break; default: break; } return tileInfo; }
private void LoadBoard(XmlElement boardElement) { int dimX = INDETERMINATE_ROW_WIDTH, dimY = boardElement.ChildNodes.Count; var rows = new List<List<TileInfo>>(); var currentRow = new List<TileInfo>(); var emptyRowIndices = new List<EmptyRowIndexStruct>(); foreach (var child in boardElement.ChildElements()) { if (child.Name == ROW_ELEMENT) { var len = child.ChildNodes.Count; if (dimX == INDETERMINATE_ROW_WIDTH) dimX = len; else if (dimX != len) Error_InconsistentBoardRowWidths(); LoadRow(child, currentRow); } else if (child.Name == EMPTY_ROW_ELEMENT) { bool rowOpen = AttemptReadOpenAttribute(child); // If we haven't yet determined the width of the board, we // have to insert it afterwards. if (dimX == INDETERMINATE_ROW_WIDTH) { emptyRowIndices.Add( new EmptyRowIndexStruct { Index = rows.Count - 1, Open = rowOpen }); continue; } else { for (int i = 0; i < dimX; i++) currentRow.Add(new TileInfo(TileType.Empty, rowOpen)); } } rows.Add(currentRow); currentRow = new List<TileInfo>(); } // If we could not determine the width of the board. This occurs when // the board is entirely composed of terminal row elements (like "<EmptyRow/>"). if (dimX == INDETERMINATE_ROW_WIDTH) Error_IndeterminateBoardWidth(); // Reinsert the empty row indices. foreach (var index in emptyRowIndices) { var newRow = new List<TileInfo>(); for (int i = 0; i < dimX; i++) newRow.Add(new TileInfo(TileType.Empty, index.Open)); rows.Insert(index.Index, newRow); } BoardDimensions = new Point(dimX, dimY); Board = new TileInfo[dimY, dimX]; var outputters = new List<Point>(); var receivers = new List<Point>(); int j = 0; foreach (var row in rows) { foreach (var info in row) { Board[j / dimX, j % dimX] = info; if (info.Type == TileType.Outputter) outputters.Add(new Point(j % dimX, j / dimX)); else if (info.Type == TileType.Receiver) receivers.Add(new Point(j % dimX, j / dimX)); j++; } } Outputters = outputters.ToArray(); Receivers = receivers.ToArray(); }