package com.bytezone.diskbrowser.wizardry; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.util.List; import com.bytezone.diskbrowser.HexFormatter; import com.bytezone.diskbrowser.applefile.AbstractFile; class MazeLevel extends AbstractFile { public int level; private List messages; private List monsters; private List items; public MazeLevel (byte[] buffer, int level) { super ("Level " + level, buffer); this.level = level; } @Override public BufferedImage getImage () { Dimension cellSize = new Dimension (22, 22); image = new BufferedImage (20 * cellSize.width + 1, 20 * cellSize.height + 1, BufferedImage.TYPE_USHORT_555_RGB); Graphics2D g = image.createGraphics (); g.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); for (int row = 0; row < 20; row++) for (int column = 0; column < 20; column++) { MazeCell cell = getLocation ((row) % 20, (column) % 20); int x = column * cellSize.width; int y = image.getHeight () - (row + 1) * cellSize.height - 1; cell.draw (g, x, y); } return image; } public void setMessages (List messages) { this.messages = messages; } public void setMonsters (List monsters) { this.monsters = monsters; } public void setItems (List items) { this.items = items; } public MazeCell getLocation (int row, int column) { MazeAddress address = new MazeAddress (level, row, column); MazeCell cell = new MazeCell (address); // doors and walls int offset = column * 6 + row / 4; // 6 bytes/column int value = HexFormatter.intValue (buffer[offset]); value >>>= (row % 4) * 2; cell.westWall = ((value & 1) == 1); value >>>= 1; cell.westDoor = ((value & 1) == 1); value = HexFormatter.intValue (buffer[offset + 120]); value >>>= (row % 4) * 2; cell.southWall = ((value & 1) == 1); value >>>= 1; cell.southDoor = ((value & 1) == 1); value = HexFormatter.intValue (buffer[offset + 240]); value >>>= (row % 4) * 2; cell.eastWall = ((value & 1) == 1); value >>>= 1; cell.eastDoor = ((value & 1) == 1); value = HexFormatter.intValue (buffer[offset + 360]); value >>>= (row % 4) * 2; cell.northWall = ((value & 1) == 1); value >>>= 1; cell.northDoor = ((value & 1) == 1); // monster table offset = column * 4 + row / 8; // 4 bytes/column, 1 bit/row value = HexFormatter.intValue (buffer[offset + 480]); value >>>= row % 8; cell.monsterLair = ((value & 1) == 1); // stairs, pits, darkness etc. offset = column * 10 + row / 2; // 10 bytes/column, 4 bits/row value = HexFormatter.intValue (buffer[offset + 560]); int b = (row % 2 == 0) ? value % 16 : value / 16; int c = HexFormatter.intValue (buffer[760 + b / 2]); int d = (b % 2 == 0) ? c % 16 : c / 16; switch (d) { case 1: cell.stairs = true; cell.addressTo = getAddress (b); break; case 2: cell.pit = true; break; case 3: cell.chute = true; cell.addressTo = getAddress (b); break; case 4: cell.spinner = true; break; case 5: cell.darkness = true; break; case 6: cell.teleport = true; cell.addressTo = getAddress (b); break; case 8: cell.elevator = true; cell.elevatorTo = HexFormatter.intValue (buffer[800 + b * 2], buffer[801 + b * 2]); cell.elevatorFrom = HexFormatter.intValue (buffer[832 + b * 2], buffer[833 + b * 2]); break; case 9: cell.rock = true; break; case 10: cell.spellsBlocked = true; break; case 11: int messageNum = HexFormatter.intValue (buffer[800 + b * 2], buffer[801 + b * 2]); for (Message m : messages) if (m.match (messageNum)) { cell.message = m; break; } if (cell.message == null) System.out.println ("message not found : " + messageNum); cell.messageType = HexFormatter.intValue (buffer[832 + b * 2], buffer[833 + b * 2]); int itemID = -1; if (cell.messageType == 2) // obtain Item { itemID = HexFormatter.intValue (buffer[768 + b * 2], buffer[769 + b * 2]); cell.itemObtained = items.get (itemID); } if (cell.messageType == 5) // requires Item { itemID = HexFormatter.intValue (buffer[768 + b * 2], buffer[769 + b * 2]); cell.itemRequired = items.get (itemID); } if (cell.messageType == 4) { value = HexFormatter.intValue (buffer[768 + b * 2], buffer[769 + b * 2]); if (value <= 100) { cell.monsterID = value; cell.monsters = monsters; } else { int val = (value - 64536) * -1; System.out.println ("Value : " + val); // this gives Index error: 20410, Size 104 in Wizardry_III/legacy2.dsk if (val < items.size ()) cell.itemObtained = items.get (val); // check this if (cell.itemObtained == null) System.out.printf ("Item %d not found%n", val); } } break; case 12: cell.monsterID = HexFormatter.intValue (buffer[832 + b * 2], buffer[833 + b * 2]); cell.monsters = monsters; break; default: cell.unknown = d; break; } return cell; } private MazeAddress getAddress (int a) { int b = a * 2; return new MazeAddress (HexFormatter.intValue (buffer[768 + b], buffer[769 + b]), HexFormatter .intValue (buffer[800 + b], buffer[801 + b]), HexFormatter.intValue (buffer[832 + b], buffer[833 + b])); } public int getRows () { return 20; } public int getColumns () { return 20; } }