method header lines

This commit is contained in:
Denis Molony 2020-02-11 17:29:55 +10:00
parent 846c975be6
commit ebeea4706d
28 changed files with 3677 additions and 3223 deletions

View File

@ -1,11 +1,15 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
public abstract class AbstractImage extends AbstractFile // -----------------------------------------------------------------------------------//
{ abstract class AbstractImage extends AbstractFile
public AbstractImage (String name, byte[] buffer) // -----------------------------------------------------------------------------------//
{ {
super (name, buffer); // ---------------------------------------------------------------------------------//
} AbstractImage (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
}
} }

View File

@ -1,325 +1,367 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
class Character extends AbstractFile // -----------------------------------------------------------------------------------//
{ class Character extends AbstractFile
private final Attributes attributes; // -----------------------------------------------------------------------------------//
private final Statistics stats; {
int scenario; private final Attributes attributes;
private final Statistics stats;
private final Collection<Spell> spellBook = new ArrayList<> (); int scenario;
private final Collection<Baggage> baggageList = new ArrayList<> ();
private final Collection<Spell> spellBook = new ArrayList<> ();
static String[] races = { "No race", "Human", "Elf", "Dwarf", "Gnome", "Hobbit" }; private final Collection<Baggage> baggageList = new ArrayList<> ();
static String[] alignments = { "Unalign", "Good", "Neutral", "Evil" };
static String[] types = static String[] races = { "No race", "Human", "Elf", "Dwarf", "Gnome", "Hobbit" };
{ "Fighter", "Mage", "Priest", "Thief", "Bishop", "Samurai", "Lord", "Ninja" }; static String[] alignments = { "Unalign", "Good", "Neutral", "Evil" };
static String[] statuses = static String[] types =
{ "OK", "Afraid", "Asleep", "Paralyze", "Stoned", "Dead", "Ashes", "Lost" }; { "Fighter", "Mage", "Priest", "Thief", "Bishop", "Samurai", "Lord", "Ninja" };
static String[] statuses =
public Character (String name, byte[] buffer, int scenario) { "OK", "Afraid", "Asleep", "Paralyze", "Stoned", "Dead", "Ashes", "Lost" };
{
super (name, buffer); // ---------------------------------------------------------------------------------//
this.scenario = scenario; Character (String name, byte[] buffer, int scenario)
// ---------------------------------------------------------------------------------//
attributes = new Attributes (); {
stats = new Statistics (); super (name, buffer);
this.scenario = scenario;
stats.race = races[buffer[34] & 0xFF];
stats.typeInt = buffer[36] & 0xFF; attributes = new Attributes ();
stats.type = types[stats.typeInt]; stats = new Statistics ();
stats.ageInWeeks = HexFormatter.intValue (buffer[38], buffer[39]);
stats.statusValue = buffer[40]; stats.race = races[buffer[34] & 0xFF];
stats.status = statuses[stats.statusValue]; stats.typeInt = buffer[36] & 0xFF;
stats.alignment = alignments[buffer[42] & 0xFF]; stats.type = types[stats.typeInt];
stats.ageInWeeks = HexFormatter.intValue (buffer[38], buffer[39]);
stats.gold = HexFormatter.intValue (buffer[52], buffer[53]) stats.statusValue = buffer[40];
+ HexFormatter.intValue (buffer[54], buffer[55]) * 10000; stats.status = statuses[stats.statusValue];
stats.experience = HexFormatter.intValue (buffer[124], buffer[125]) stats.alignment = alignments[buffer[42] & 0xFF];
+ HexFormatter.intValue (buffer[126], buffer[127]) * 10000;
stats.level = HexFormatter.intValue (buffer[132], buffer[133]); stats.gold = HexFormatter.intValue (buffer[52], buffer[53])
+ HexFormatter.intValue (buffer[54], buffer[55]) * 10000;
stats.hitsLeft = HexFormatter.intValue (buffer[134], buffer[135]); stats.experience = HexFormatter.intValue (buffer[124], buffer[125])
stats.hitsMax = HexFormatter.intValue (buffer[136], buffer[137]); + HexFormatter.intValue (buffer[126], buffer[127]) * 10000;
stats.armourClass = buffer[176]; stats.level = HexFormatter.intValue (buffer[132], buffer[133]);
attributes.strength = (buffer[44] & 0xFF) % 16; stats.hitsLeft = HexFormatter.intValue (buffer[134], buffer[135]);
if (attributes.strength < 3) stats.hitsMax = HexFormatter.intValue (buffer[136], buffer[137]);
attributes.strength += 16; stats.armourClass = buffer[176];
attributes.array[0] = attributes.strength;
attributes.strength = (buffer[44] & 0xFF) % 16;
int i1 = (buffer[44] & 0xFF) / 16; if (attributes.strength < 3)
int i2 = (buffer[45] & 0xFF) % 4; attributes.strength += 16;
attributes.intelligence = i1 / 2 + i2 * 8; attributes.array[0] = attributes.strength;
attributes.array[1] = attributes.intelligence;
int i1 = (buffer[44] & 0xFF) / 16;
attributes.piety = (buffer[45] & 0xFF) / 4; int i2 = (buffer[45] & 0xFF) % 4;
attributes.array[2] = attributes.piety; attributes.intelligence = i1 / 2 + i2 * 8;
attributes.array[1] = attributes.intelligence;
attributes.vitality = (buffer[46] & 0xFF) % 16;
if (attributes.vitality < 3) attributes.piety = (buffer[45] & 0xFF) / 4;
attributes.vitality += 16; attributes.array[2] = attributes.piety;
attributes.array[3] = attributes.vitality;
attributes.vitality = (buffer[46] & 0xFF) % 16;
int a1 = (buffer[46] & 0xFF) / 16; if (attributes.vitality < 3)
int a2 = (buffer[47] & 0xFF) % 4; attributes.vitality += 16;
attributes.agility = a1 / 2 + a2 * 8; attributes.array[3] = attributes.vitality;
attributes.array[4] = attributes.agility;
int a1 = (buffer[46] & 0xFF) / 16;
attributes.luck = (buffer[47] & 0xFF) / 4; int a2 = (buffer[47] & 0xFF) % 4;
attributes.array[5] = attributes.luck; attributes.agility = a1 / 2 + a2 * 8;
} attributes.array[4] = attributes.agility;
public void linkItems (List<Item> itemList) attributes.luck = (buffer[47] & 0xFF) / 4;
{ attributes.array[5] = attributes.luck;
boolean equipped; }
boolean identified;
int totItems = buffer[58]; // ---------------------------------------------------------------------------------//
stats.assetValue = 0; public void linkItems (List<Item> itemList)
// ---------------------------------------------------------------------------------//
for (int ptr = 60; totItems > 0; ptr += 8, totItems--) {
{ boolean equipped;
int itemID = buffer[ptr + 6] & 0xFF; boolean identified;
if (scenario == 3) int totItems = buffer[58];
itemID = (itemID + 24) % 256; stats.assetValue = 0;
if (itemID >= 0 && itemID < itemList.size ())
{ for (int ptr = 60; totItems > 0; ptr += 8, totItems--)
Item item = itemList.get (itemID); {
equipped = (buffer[ptr] == 1); int itemID = buffer[ptr + 6] & 0xFF;
identified = (buffer[ptr + 4] == 1); if (scenario == 3)
baggageList.add (new Baggage (item, equipped, identified)); itemID = (itemID + 24) % 256;
stats.assetValue += item.getCost (); if (itemID >= 0 && itemID < itemList.size ())
item.partyOwns++; {
} Item item = itemList.get (itemID);
else equipped = (buffer[ptr] == 1);
System.out.println (name + " ItemID : " + itemID + " is outside range 0:" identified = (buffer[ptr + 4] == 1);
+ (itemList.size () - 1)); baggageList.add (new Baggage (item, equipped, identified));
} stats.assetValue += item.getCost ();
} item.partyOwns++;
}
public void linkSpells (List<Spell> spellList) else
{ System.out.println (name + " ItemID : " + itemID + " is outside range 0:"
for (int i = 138; i < 145; i++) + (itemList.size () - 1));
for (int bit = 0; bit < 8; bit++) }
if (((buffer[i] >>> bit) & 1) == 1) }
{
int index = (i - 138) * 8 + bit; // ---------------------------------------------------------------------------------//
if (index > 0 && index <= spellList.size ()) public void linkSpells (List<Spell> spellList)
spellBook.add (spellList.get (index - 1)); // ---------------------------------------------------------------------------------//
else {
System.out.println ("LinkSpell: " + name + " SpellID : " + index for (int i = 138; i < 145; i++)
+ " is outside range 1:" + spellList.size ()); for (int bit = 0; bit < 8; bit++)
} if (((buffer[i] >>> bit) & 1) == 1)
} {
int index = (i - 138) * 8 + bit;
@Override if (index > 0 && index <= spellList.size ())
public String getText () spellBook.add (spellList.get (index - 1));
{ else
StringBuilder text = new StringBuilder (); System.out.println ("LinkSpell: " + name + " SpellID : " + index
+ " is outside range 1:" + spellList.size ());
text.append ("Character name ..... " + name); }
text.append ("\n\nRace ............... " + stats.race); }
text.append ("\nType ............... " + stats.type);
text.append ("\nAlignment .......... " + stats.alignment); // ---------------------------------------------------------------------------------//
text.append ("\nStatus ............. " + stats.status); @Override
// text.append ("\nType ............... " + stats.typeInt); public String getText ()
// text.append ("\nStatus ............. " + stats.statusValue); // ---------------------------------------------------------------------------------//
text.append ("\nGold ............... " + String.format ("%,d", stats.gold)); {
text.append ("\nExperience ......... " + String.format ("%,d", stats.experience)); StringBuilder text = new StringBuilder ();
text.append ("\nNext level ......... " + String.format ("%,d", stats.nextLevel));
text.append ("\nLevel .............. " + stats.level); text.append ("Character name ..... " + name);
text.append ("\nAge in weeks ....... " text.append ("\n\nRace ............... " + stats.race);
+ String.format ("%,d (%d)", stats.ageInWeeks, (stats.ageInWeeks / 52))); text.append ("\nType ............... " + stats.type);
text.append ("\nHit points left .... " + stats.hitsLeft); text.append ("\nAlignment .......... " + stats.alignment);
text.append ("\nMaximum hits ....... " + stats.hitsMax); text.append ("\nStatus ............. " + stats.status);
text.append ("\nArmour class ....... " + stats.armourClass); // text.append ("\nType ............... " + stats.typeInt);
text.append ("\nAsset value ........ " + String.format ("%,d", stats.assetValue)); // text.append ("\nStatus ............. " + stats.statusValue);
text.append ("\nAwards ............. " + isWinner ()); text.append ("\nGold ............... " + String.format ("%,d", stats.gold));
text.append ("\nOut ................ " + isOut ()); text.append ("\nExperience ......... " + String.format ("%,d", stats.experience));
text.append ("\n\nStrength ........... " + attributes.strength); text.append ("\nNext level ......... " + String.format ("%,d", stats.nextLevel));
text.append ("\nIntelligence ....... " + attributes.intelligence); text.append ("\nLevel .............. " + stats.level);
text.append ("\nPiety .............. " + attributes.piety); text.append ("\nAge in weeks ....... "
text.append ("\nVitality ........... " + attributes.vitality); + String.format ("%,d (%d)", stats.ageInWeeks, (stats.ageInWeeks / 52)));
text.append ("\nAgility ............ " + attributes.agility); text.append ("\nHit points left .... " + stats.hitsLeft);
text.append ("\nLuck ............... " + attributes.luck); text.append ("\nMaximum hits ....... " + stats.hitsMax);
text.append ("\nArmour class ....... " + stats.armourClass);
int[] spellPoints = getMageSpellPoints (); text.append ("\nAsset value ........ " + String.format ("%,d", stats.assetValue));
text.append ("\n\nMage spell points .."); text.append ("\nAwards ............. " + isWinner ());
for (int i = 0; i < spellPoints.length; i++) text.append ("\nOut ................ " + isOut ());
text.append (" " + spellPoints[i]); text.append ("\n\nStrength ........... " + attributes.strength);
text.append ("\nIntelligence ....... " + attributes.intelligence);
spellPoints = getPriestSpellPoints (); text.append ("\nPiety .............. " + attributes.piety);
text.append ("\nPriest spell points "); text.append ("\nVitality ........... " + attributes.vitality);
for (int i = 0; i < spellPoints.length; i++) text.append ("\nAgility ............ " + attributes.agility);
text.append (" " + spellPoints[i]); text.append ("\nLuck ............... " + attributes.luck);
text.append ("\n\nSpells :"); int[] spellPoints = getMageSpellPoints ();
for (Spell s : spellBook) text.append ("\n\nMage spell points ..");
text.append ("\n" + s); for (int i = 0; i < spellPoints.length; i++)
text.append (" " + spellPoints[i]);
text.append ("\n\nItems :");
for (Baggage b : baggageList) spellPoints = getPriestSpellPoints ();
text.append ("\n" + b); text.append ("\nPriest spell points ");
for (int i = 0; i < spellPoints.length; i++)
return text.toString (); text.append (" " + spellPoints[i]);
}
text.append ("\n\nSpells :");
public void linkExperience (ExperienceLevel exp) for (Spell s : spellBook)
{ text.append ("\n" + s);
stats.nextLevel = exp.getExperiencePoints (stats.level);
} text.append ("\n\nItems :");
for (Baggage b : baggageList)
public int[] getMageSpellPoints () text.append ("\n" + b);
{
int[] spells = new int[7]; return text.toString ();
}
for (int i = 0; i < 7; i++)
spells[i] = buffer[146 + i * 2]; // ---------------------------------------------------------------------------------//
public void linkExperience (ExperienceLevel exp)
return spells; // ---------------------------------------------------------------------------------//
} {
stats.nextLevel = exp.getExperiencePoints (stats.level);
public int[] getPriestSpellPoints () }
{
int[] spells = new int[7]; // ---------------------------------------------------------------------------------//
public int[] getMageSpellPoints ()
for (int i = 0; i < 7; i++) // ---------------------------------------------------------------------------------//
spells[i] = buffer[160 + i * 2]; {
int[] spells = new int[7];
return spells;
} for (int i = 0; i < 7; i++)
spells[i] = buffer[146 + i * 2];
public Long getNextLevel ()
{ return spells;
return stats.nextLevel; }
}
// ---------------------------------------------------------------------------------//
// this is temporary until I have more data public int[] getPriestSpellPoints ()
public String isWinner () // ---------------------------------------------------------------------------------//
{ {
int v1 = buffer[206]; int[] spells = new int[7];
int v2 = buffer[207];
if (v1 == 0x01) for (int i = 0; i < 7; i++)
return ">"; spells[i] = buffer[160 + i * 2];
if (v1 == 0x00 && v2 == 0x00)
return ""; return spells;
if (v1 == 0x00 && v2 == 0x20) }
return "D";
if (v1 == 0x20 && v2 == 0x20) // ---------------------------------------------------------------------------------//
return "*D"; public Long getNextLevel ()
if (v1 == 0x21 && v2 == 0x60) // ---------------------------------------------------------------------------------//
return ">*DG"; {
if (v1 == 0x21 && v2 == 0x28) return stats.nextLevel;
return ">*KD"; }
return "Unknown : " + v1 + " " + v2;
} // this is temporary until I have more data
// ---------------------------------------------------------------------------------//
public boolean isOut () public String isWinner ()
{ // ---------------------------------------------------------------------------------//
return (buffer[32] == 1); {
} int v1 = buffer[206];
int v2 = buffer[207];
public String getType () if (v1 == 0x01)
{ return ">";
return stats.type; if (v1 == 0x00 && v2 == 0x00)
} return "";
if (v1 == 0x00 && v2 == 0x20)
public String getRace () return "D";
{ if (v1 == 0x20 && v2 == 0x20)
return stats.race; return "*D";
} if (v1 == 0x21 && v2 == 0x60)
return ">*DG";
public String getAlignment () if (v1 == 0x21 && v2 == 0x28)
{ return ">*KD";
return stats.alignment; return "Unknown : " + v1 + " " + v2;
} }
public Attributes getAttributes () // ---------------------------------------------------------------------------------//
{ public boolean isOut ()
return attributes; // ---------------------------------------------------------------------------------//
} {
return (buffer[32] == 1);
public Statistics getStatistics () }
{
return stats; // ---------------------------------------------------------------------------------//
} public String getType ()
// ---------------------------------------------------------------------------------//
public Iterator<Baggage> getBaggage () {
{ return stats.type;
return baggageList.iterator (); }
}
// ---------------------------------------------------------------------------------//
public Iterator<Spell> getSpells () public String getRace ()
{ // ---------------------------------------------------------------------------------//
return spellBook.iterator (); {
} return stats.race;
}
@Override
public String toString () // ---------------------------------------------------------------------------------//
{ public String getAlignment ()
return name; // ---------------------------------------------------------------------------------//
} {
return stats.alignment;
public class Baggage }
{
public Item item; // ---------------------------------------------------------------------------------//
public boolean equipped; public Attributes getAttributes ()
public boolean identified; // ---------------------------------------------------------------------------------//
{
public Baggage (Item item, boolean equipped, boolean identified) return attributes;
{ }
this.item = item;
this.equipped = equipped; // ---------------------------------------------------------------------------------//
this.identified = identified; public Statistics getStatistics ()
} // ---------------------------------------------------------------------------------//
{
@Override return stats;
public String toString () }
{
return String.format ("%s%-15s (%d)", equipped ? "*" : " ", item.getName (), // ---------------------------------------------------------------------------------//
item.getCost ()); public Iterator<Baggage> getBaggage ()
} // ---------------------------------------------------------------------------------//
} {
return baggageList.iterator ();
public class Statistics implements Cloneable }
{
public String race; // ---------------------------------------------------------------------------------//
public String type; public Iterator<Spell> getSpells ()
public String alignment; // ---------------------------------------------------------------------------------//
public String status; {
public int typeInt; return spellBook.iterator ();
public int statusValue; }
public int gold;
public int experience; // ---------------------------------------------------------------------------------//
public long nextLevel; @Override
public int level; public String toString ()
public int ageInWeeks; // ---------------------------------------------------------------------------------//
public int hitsLeft; {
public int hitsMax; return name;
public int armourClass; }
public int assetValue;
} // ---------------------------------------------------------------------------------//
public class Baggage
public class Attributes // ---------------------------------------------------------------------------------//
{ {
public int strength; public Item item;
public int intelligence; public boolean equipped;
public int piety; public boolean identified;
public int vitality;
public int agility; public Baggage (Item item, boolean equipped, boolean identified)
public int luck; {
public int[] array; this.item = item;
this.equipped = equipped;
public Attributes () this.identified = identified;
{ }
array = new int[6];
} @Override
} public String toString ()
{
return String.format ("%s%-15s (%d)", equipped ? "*" : " ", item.getName (),
item.getCost ());
}
}
// ---------------------------------------------------------------------------------//
public class Statistics implements Cloneable
// ---------------------------------------------------------------------------------//
{
public String race;
public String type;
public String alignment;
public String status;
public int typeInt;
public int statusValue;
public int gold;
public int experience;
public long nextLevel;
public int level;
public int ageInWeeks;
public int hitsLeft;
public int hitsMax;
public int armourClass;
public int assetValue;
}
public class Attributes
{
public int strength;
public int intelligence;
public int piety;
public int vitality;
public int agility;
public int luck;
public int[] array;
public Attributes ()
{
array = new int[6];
}
}
} }

View File

@ -1,27 +1,33 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
class CodedMessage extends Message // -----------------------------------------------------------------------------------//
{ class CodedMessage extends Message
public static int codeOffset = 185; // -----------------------------------------------------------------------------------//
{
public CodedMessage (byte[] buffer) public static int codeOffset = 185;
{
super (buffer); // ---------------------------------------------------------------------------------//
} CodedMessage (byte[] buffer)
// ---------------------------------------------------------------------------------//
@Override {
protected String getLine (int offset) super (buffer);
{ }
int length = buffer[offset] & 0xFF;
byte[] translation = new byte[length]; // ---------------------------------------------------------------------------------//
codeOffset--; @Override
for (int j = 0; j < length; j++) protected String getLine (int offset)
{ // ---------------------------------------------------------------------------------//
translation[j] = buffer[offset + 1 + j]; {
translation[j] -= codeOffset - j * 3; int length = buffer[offset] & 0xFF;
} byte[] translation = new byte[length];
return HexFormatter.getString (translation, 0, length); codeOffset--;
} for (int j = 0; j < length; j++)
{
translation[j] = buffer[offset + 1 + j];
translation[j] -= codeOffset - j * 3;
}
return HexFormatter.getString (translation, 0, length);
}
} }

View File

@ -1,27 +1,33 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
class Dice // -----------------------------------------------------------------------------------//
{ class Dice
int qty; // -----------------------------------------------------------------------------------//
int sides; {
int bonus; int qty;
int sides;
public Dice (byte[] buffer, int offset) int bonus;
{
qty = buffer[offset]; // ---------------------------------------------------------------------------------//
sides = buffer[offset + 2]; Dice (byte[] buffer, int offset)
bonus = buffer[offset + 4]; // ---------------------------------------------------------------------------------//
} {
qty = buffer[offset];
@Override sides = buffer[offset + 2];
public String toString () bonus = buffer[offset + 4];
{ }
if (qty == 0)
return ""; // ---------------------------------------------------------------------------------//
StringBuilder text = new StringBuilder (); @Override
text.append (String.format ("%dd%d", qty, sides)); public String toString ()
if (bonus > 0) // ---------------------------------------------------------------------------------//
text.append ("+" + bonus); {
return text.toString (); if (qty == 0)
} return "";
StringBuilder text = new StringBuilder ();
text.append (String.format ("%dd%d", qty, sides));
if (bonus > 0)
text.append ("+" + bonus);
return text.toString ();
}
} }

View File

@ -2,15 +2,21 @@ package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
public class DragonData extends AbstractFile // -----------------------------------------------------------------------------------//
class DragonData extends AbstractFile
// -----------------------------------------------------------------------------------//
{ {
public DragonData (String name, byte[] buffer) // ---------------------------------------------------------------------------------//
DragonData (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{ {
super (name, buffer); super (name, buffer);
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public String getText () public String getText ()
// ---------------------------------------------------------------------------------//
{ {
return "DragonData"; return "DragonData";
} }

View File

@ -1,44 +1,51 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
class ExperienceLevel extends AbstractFile // -----------------------------------------------------------------------------------//
{ class ExperienceLevel extends AbstractFile
private final long[] expLevels = new long[13]; // -----------------------------------------------------------------------------------//
{
public ExperienceLevel (String name, byte[] buffer) private final long[] expLevels = new long[13];
{
super (name, buffer); // ---------------------------------------------------------------------------------//
ExperienceLevel (String name, byte[] buffer)
int seq = 0; // ---------------------------------------------------------------------------------//
{
for (int ptr = 0; ptr < buffer.length; ptr += 6) super (name, buffer);
{
if (buffer[ptr] == 0) int seq = 0;
break;
for (int ptr = 0; ptr < buffer.length; ptr += 6)
long points = {
HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]) if (buffer[ptr] == 0)
+ HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]) * 10000 break;
+ HexFormatter.intValue (buffer[ptr + 4], buffer[ptr + 5]) * 100000000L;
expLevels[seq++] = points; long points = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1])
} + HexFormatter.intValue (buffer[ptr + 2], buffer[ptr + 3]) * 10000
} + HexFormatter.intValue (buffer[ptr + 4], buffer[ptr + 5]) * 100000000L;
expLevels[seq++] = points;
public long getExperiencePoints (int level) }
{ }
if (level < 13)
return expLevels[level]; // ---------------------------------------------------------------------------------//
return (level - 12) * expLevels[0] + expLevels[12]; long getExperiencePoints (int level)
} // ---------------------------------------------------------------------------------//
{
@Override if (level < 13)
public String getText () return expLevels[level];
{ return (level - 12) * expLevels[0] + expLevels[12];
StringBuilder line = new StringBuilder (); }
for (long exp : expLevels)
line.append (exp + "\n"); // ---------------------------------------------------------------------------------//
return line.toString (); @Override
} public String getText ()
// ---------------------------------------------------------------------------------//
{
StringBuilder line = new StringBuilder ();
for (long exp : expLevels)
line.append (exp + "\n");
return line.toString ();
}
} }

View File

@ -1,239 +1,253 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultMutableTreeNode;
import com.bytezone.diskbrowser.applefile.AppleFileSource; import com.bytezone.diskbrowser.applefile.AppleFileSource;
import com.bytezone.diskbrowser.applefile.DefaultAppleFile; import com.bytezone.diskbrowser.applefile.DefaultAppleFile;
import com.bytezone.diskbrowser.disk.DefaultAppleFileSource; import com.bytezone.diskbrowser.disk.DefaultAppleFileSource;
import com.bytezone.diskbrowser.disk.DiskAddress; import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.disk.FormattedDisk; import com.bytezone.diskbrowser.disk.FormattedDisk;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
class Header // -----------------------------------------------------------------------------------//
{ class Header
static String[] typeText = { "header", "maze", "monsters", "rewards", "items", // -----------------------------------------------------------------------------------//
"characters", "images", "char levels" }; {
static String[] scenarioNames = static String[] typeText = { "header", "maze", "monsters", "rewards", "items",
{ "PROVING GROUNDS OF THE MAD OVERLORD!", "THE KNIGHT OF DIAMONDS", "characters", "images", "char levels" };
"THE LEGACY OF LLYLGAMYN", "THE RETURN OF WERDNA" }; static String[] scenarioNames =
{ "PROVING GROUNDS OF THE MAD OVERLORD!", "THE KNIGHT OF DIAMONDS",
static final int MAZE_AREA = 1; "THE LEGACY OF LLYLGAMYN", "THE RETURN OF WERDNA" };
static final int MONSTER_AREA = 2;
static final int TREASURE_TABLE_AREA = 3; static final int MAZE_AREA = 1;
static final int ITEM_AREA = 4; static final int MONSTER_AREA = 2;
static final int CHARACTER_AREA = 5; static final int TREASURE_TABLE_AREA = 3;
static final int IMAGE_AREA = 6; static final int ITEM_AREA = 4;
static final int EXPERIENCE_AREA = 7; static final int CHARACTER_AREA = 5;
static final int IMAGE_AREA = 6;
String scenarioTitle; static final int EXPERIENCE_AREA = 7;
public int scenarioID;
List<ScenarioData> data = new ArrayList<> (8); String scenarioTitle;
FormattedDisk owner; public int scenarioID;
List<ScenarioData> data = new ArrayList<> (8);
public Header (DefaultMutableTreeNode dataNode, FormattedDisk owner) FormattedDisk owner;
{
this.owner = owner; // ---------------------------------------------------------------------------------//
Header (DefaultMutableTreeNode dataNode, FormattedDisk owner)
AppleFileSource afs = (AppleFileSource) dataNode.getUserObject (); // ---------------------------------------------------------------------------------//
List<DiskAddress> sectors = afs.getSectors (); {
DefaultAppleFile daf = (DefaultAppleFile) afs.getDataSource (); this.owner = owner;
scenarioTitle = HexFormatter.getPascalString (daf.buffer, 0);
AppleFileSource afs = (AppleFileSource) dataNode.getUserObject ();
while (scenarioID < scenarioNames.length) List<DiskAddress> sectors = afs.getSectors ();
if (scenarioNames[scenarioID++].equals (scenarioTitle)) DefaultAppleFile daf = (DefaultAppleFile) afs.getDataSource ();
break; scenarioTitle = HexFormatter.getPascalString (daf.buffer, 0);
if (scenarioID > scenarioNames.length) while (scenarioID < scenarioNames.length)
System.out.println ("Invalid scenario ID : " + scenarioID + " " + scenarioTitle); if (scenarioNames[scenarioID++].equals (scenarioTitle))
break;
for (int i = 0; i < 8; i++)
data.add (new ScenarioData (daf.buffer, i, sectors)); if (scenarioID > scenarioNames.length)
System.out.println ("Invalid scenario ID : " + scenarioID + " " + scenarioTitle);
StringBuilder text = new StringBuilder ("Data type Offset Size Units ???\n"
+ "------------ ------ ----- ----- -----\n"); for (int i = 0; i < 8; i++)
data.add (new ScenarioData (daf.buffer, i, sectors));
for (ScenarioData sd : data)
text.append (sd + "\n"); StringBuilder text = new StringBuilder ("Data type Offset Size Units ???\n"
+ "------------ ------ ----- ----- -----\n");
daf.setText (text.toString ());
for (ScenarioData sd : data)
text = new StringBuilder (scenarioTitle + "\n\n"); text.append (sd + "\n");
int ptr = 106; daf.setText (text.toString ());
while (daf.buffer[ptr] != -1)
{ text = new StringBuilder (scenarioTitle + "\n\n");
text.append (HexFormatter.getPascalString (daf.buffer, ptr) + "\n");
ptr += 10; int ptr = 106;
} while (daf.buffer[ptr] != -1)
{
DefaultAppleFileSource dafs = text.append (HexFormatter.getPascalString (daf.buffer, ptr) + "\n");
new DefaultAppleFileSource ("Header", text.toString (), owner); ptr += 10;
dafs.setSectors (data.get (0).sectors); }
DefaultMutableTreeNode headerNode = new DefaultMutableTreeNode (dafs);
dataNode.add (headerNode); DefaultAppleFileSource dafs =
new DefaultAppleFileSource ("Header", text.toString (), owner);
if (scenarioID > 3) dafs.setSectors (data.get (0).sectors);
return; DefaultMutableTreeNode headerNode = new DefaultMutableTreeNode (dafs);
dataNode.add (headerNode);
int totalBlocks = data.get (0).sectors.size ();
linkText ("Text", data.get (0).sectors.get (0), headerNode); if (scenarioID > 3)
return;
if (scenarioID < 3)
{ int totalBlocks = data.get (0).sectors.size ();
linkPictures ("Alphabet", data.get (0).sectors.get (1), headerNode); linkText ("Text", data.get (0).sectors.get (0), headerNode);
linkPictures ("Graphics", data.get (0).sectors.get (2), headerNode);
linkPictures ("Unknown", data.get (0).sectors.get (3), headerNode); if (scenarioID < 3)
} {
linkPictures ("Alphabet", data.get (0).sectors.get (1), headerNode);
linkSpells ("Mage spells", data.get (0).sectors.get (totalBlocks - 2), headerNode); linkPictures ("Graphics", data.get (0).sectors.get (2), headerNode);
linkSpells ("Priest spells", data.get (0).sectors.get (totalBlocks - 1), headerNode); linkPictures ("Unknown", data.get (0).sectors.get (3), headerNode);
}
if (false && scenarioID <= 2)
{ linkSpells ("Mage spells", data.get (0).sectors.get (totalBlocks - 2), headerNode);
System.out.println (printChars (daf.buffer, 1)); linkSpells ("Priest spells", data.get (0).sectors.get (totalBlocks - 1), headerNode);
System.out.println (printChars (daf.buffer, 2));
} if (false && scenarioID <= 2)
} {
System.out.println (printChars (daf.buffer, 1));
private void linkText (String title, DiskAddress da, DefaultMutableTreeNode headerNode) System.out.println (printChars (daf.buffer, 2));
{ }
List<DiskAddress> blocks = new ArrayList<> (); }
blocks.add (da);
// ---------------------------------------------------------------------------------//
StringBuilder text = new StringBuilder (scenarioTitle + "\n\n"); private void linkText (String title, DiskAddress da, DefaultMutableTreeNode headerNode)
// ---------------------------------------------------------------------------------//
int ptr = 106; {
byte[] buffer = owner.getDisk ().readSector (da); List<DiskAddress> blocks = new ArrayList<> ();
while (buffer[ptr] != -1) blocks.add (da);
{
text.append (HexFormatter.getPascalString (buffer, ptr) + "\n"); StringBuilder text = new StringBuilder (scenarioTitle + "\n\n");
ptr += 10;
} int ptr = 106;
ptr += 2; byte[] buffer = owner.getDisk ().readSector (da);
text.append ("\n"); while (buffer[ptr] != -1)
while (ptr < 512) {
{ text.append (HexFormatter.getPascalString (buffer, ptr) + "\n");
int value = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]); ptr += 10;
text.append (String.format ("%04X %,6d%n", value, value)); }
ptr += 2; ptr += 2;
} text.append ("\n");
while (ptr < 512)
DefaultAppleFileSource dafs = {
new DefaultAppleFileSource (title, text.toString (), owner); int value = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
dafs.setSectors (blocks); text.append (String.format ("%04X %,6d%n", value, value));
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs); ptr += 2;
node.setAllowsChildren (false); }
headerNode.add (node);
} DefaultAppleFileSource dafs =
new DefaultAppleFileSource (title, text.toString (), owner);
private void linkPictures (String title, DiskAddress da, dafs.setSectors (blocks);
DefaultMutableTreeNode headerNode) DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
{ node.setAllowsChildren (false);
List<DiskAddress> blocks = new ArrayList<> (); headerNode.add (node);
blocks.add (da); }
byte[] buffer = owner.getDisk ().readSector (da); // ---------------------------------------------------------------------------------//
String text = printChars (buffer, 0); private void linkPictures (String title, DiskAddress da,
DefaultMutableTreeNode headerNode)
DefaultAppleFileSource dafs = new DefaultAppleFileSource (title, text, owner); // ---------------------------------------------------------------------------------//
dafs.setSectors (blocks); {
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs); List<DiskAddress> blocks = new ArrayList<> ();
node.setAllowsChildren (false); blocks.add (da);
headerNode.add (node);
} byte[] buffer = owner.getDisk ().readSector (da);
String text = printChars (buffer, 0);
private void linkSpells (String title, DiskAddress da,
DefaultMutableTreeNode headerNode) DefaultAppleFileSource dafs = new DefaultAppleFileSource (title, text, owner);
{ dafs.setSectors (blocks);
List<DiskAddress> blocks = new ArrayList<> (); DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
blocks.add (da); node.setAllowsChildren (false);
int level = 1; headerNode.add (node);
}
StringBuilder list = new StringBuilder ("Level " + level + ":\n");
byte[] buffer = owner.getDisk ().readSector (da); // ---------------------------------------------------------------------------------//
String text = HexFormatter.getString (buffer, 0, 512); private void linkSpells (String title, DiskAddress da,
String[] spells = text.split ("\n"); DefaultMutableTreeNode headerNode)
for (String s : spells) // ---------------------------------------------------------------------------------//
{ {
if (s.length () == 0) List<DiskAddress> blocks = new ArrayList<> ();
break; blocks.add (da);
if (s.startsWith ("*")) int level = 1;
{
s = s.substring (1); StringBuilder list = new StringBuilder ("Level " + level + ":\n");
level++; byte[] buffer = owner.getDisk ().readSector (da);
list.append ("\nLevel " + level + ":\n"); String text = HexFormatter.getString (buffer, 0, 512);
} String[] spells = text.split ("\n");
list.append (" " + s + "\n"); for (String s : spells)
} {
if (s.length () == 0)
DefaultAppleFileSource dafs = break;
new DefaultAppleFileSource (title, list.toString (), owner); if (s.startsWith ("*"))
dafs.setSectors (blocks); {
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs); s = s.substring (1);
node.setAllowsChildren (false); level++;
headerNode.add (node); list.append ("\nLevel " + level + ":\n");
} }
list.append (" " + s + "\n");
private String printChars (byte[] buffer, int block) }
{
StringBuilder text = new StringBuilder (); DefaultAppleFileSource dafs =
for (int i = block * 512; i < (block + 1) * 512; i += 64) new DefaultAppleFileSource (title, list.toString (), owner);
{ dafs.setSectors (blocks);
for (int line = 0; line < 8; line++) DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
{ node.setAllowsChildren (false);
for (int j = 0; j < 8; j++) headerNode.add (node);
{ }
int value = buffer[i + line + j * 8] & 0xFF;
for (int bit = 0; bit < 7; bit++) // ---------------------------------------------------------------------------------//
{ private String printChars (byte[] buffer, int block)
if ((value & 0x01) == 1) // ---------------------------------------------------------------------------------//
text.append ("O"); {
else StringBuilder text = new StringBuilder ();
text.append ("."); for (int i = block * 512; i < (block + 1) * 512; i += 64)
value >>= 1; {
} for (int line = 0; line < 8; line++)
text.append (" "); {
} for (int j = 0; j < 8; j++)
text.append ("\n"); {
} int value = buffer[i + line + j * 8] & 0xFF;
text.append ("\n"); for (int bit = 0; bit < 7; bit++)
} {
return text.toString (); if ((value & 0x01) == 1)
} text.append ("O");
else
// this could be the base factory class for all Wizardry types text.append (".");
class ScenarioData value >>= 1;
{ }
int dunno; text.append (" ");
int total; }
int totalBlocks; text.append ("\n");
int dataOffset; }
int type; text.append ("\n");
List<DiskAddress> sectors; }
return text.toString ();
public ScenarioData (byte[] buffer, int seq, List<DiskAddress> sectors) }
{
int offset = 42 + seq * 2; // this could be the base factory class for all Wizardry types
dunno = buffer[offset] & 0xFF; // ---------------------------------------------------------------------------------//
total = buffer[offset + 16] & 0xFF; class ScenarioData
totalBlocks = buffer[offset + 32] & 0xFF; // ---------------------------------------------------------------------------------//
dataOffset = buffer[offset + 48] & 0xFF; {
type = seq; int dunno;
int total;
this.sectors = new ArrayList<> (totalBlocks); int totalBlocks;
for (int i = dataOffset, max = dataOffset + totalBlocks; i < max; i++) int dataOffset;
if (i < sectors.size ()) int type;
this.sectors.add (sectors.get (i)); List<DiskAddress> sectors;
}
public ScenarioData (byte[] buffer, int seq, List<DiskAddress> sectors)
@Override {
public String toString () int offset = 42 + seq * 2;
{ dunno = buffer[offset] & 0xFF;
return String.format ("%-15s %3d %3d %3d %3d", typeText[type], dataOffset, total = buffer[offset + 16] & 0xFF;
totalBlocks, total, dunno); totalBlocks = buffer[offset + 32] & 0xFF;
} dataOffset = buffer[offset + 48] & 0xFF;
} type = seq;
this.sectors = new ArrayList<> (totalBlocks);
for (int i = dataOffset, max = dataOffset + totalBlocks; i < max; i++)
if (i < sectors.size ())
this.sectors.add (sectors.get (i));
}
@Override
public String toString ()
{
return String.format ("%-15s %3d %3d %3d %3d", typeText[type], dataOffset,
totalBlocks, total, dunno);
}
}
} }

View File

@ -7,7 +7,9 @@ import com.bytezone.diskbrowser.applefile.AbstractFile;
// link for possible display algorithm: // link for possible display algorithm:
// http://stackoverflow.com/questions/14184655/set-position-for-drawing-binary-tree // http://stackoverflow.com/questions/14184655/set-position-for-drawing-binary-tree
public class Huffman extends AbstractFile // -----------------------------------------------------------------------------------//
class Huffman extends AbstractFile
// -----------------------------------------------------------------------------------//
{ {
private static final byte[] mask = { 2, 1 }; // bits: 10 or 01 private static final byte[] mask = { 2, 1 }; // bits: 10 or 01
private static final int[] offset = { 512, 256 }; // offset to left/right nodes private static final int[] offset = { 512, 256 }; // offset to left/right nodes
@ -19,12 +21,16 @@ public class Huffman extends AbstractFile
private String bufferContents; private String bufferContents;
public Huffman (String name, byte[] buffer) // ---------------------------------------------------------------------------------//
Huffman (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{ {
super (name, buffer); super (name, buffer);
} }
public String decodeMessage (byte[] message) // ---------------------------------------------------------------------------------//
String decodeMessage (byte[] message)
// ---------------------------------------------------------------------------------//
{ {
this.message = message; this.message = message;
depth = 0; depth = 0;
@ -39,7 +45,9 @@ public class Huffman extends AbstractFile
return text.toString (); return text.toString ();
} }
// ---------------------------------------------------------------------------------//
private byte getChar () private byte getChar ()
// ---------------------------------------------------------------------------------//
{ {
int treePtr = 0; // start at the root int treePtr = 0; // start at the root
@ -63,8 +71,10 @@ public class Huffman extends AbstractFile
} }
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public String getText () public String getText ()
// ---------------------------------------------------------------------------------//
{ {
if (bufferContents == null) if (bufferContents == null)
{ {
@ -75,7 +85,9 @@ public class Huffman extends AbstractFile
return bufferContents; return bufferContents;
} }
// ---------------------------------------------------------------------------------//
private void walk (int treePtr, String path, StringBuilder text) private void walk (int treePtr, String path, StringBuilder text)
// ---------------------------------------------------------------------------------//
{ {
for (int currentBit = 1; currentBit >= 0; --currentBit) for (int currentBit = 1; currentBit >= 0; --currentBit)
if ((buffer[treePtr] & mask[currentBit]) == 0) if ((buffer[treePtr] & mask[currentBit]) == 0)

View File

@ -1,59 +1,65 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer; import java.awt.image.DataBuffer;
class Image extends AbstractImage // -----------------------------------------------------------------------------------//
{ class Image extends AbstractImage
public Image (String name, byte[] buffer) // -----------------------------------------------------------------------------------//
{ {
super (name, buffer); // ---------------------------------------------------------------------------------//
Image (String name, byte[] buffer)
if (buffer[0] == -61 && buffer[1] == -115) // ---------------------------------------------------------------------------------//
fixSlime (buffer); {
super (name, buffer);
image = new BufferedImage (70, 50, BufferedImage.TYPE_BYTE_GRAY); // width/height
DataBuffer db = image.getRaster ().getDataBuffer (); if (buffer[0] == -61 && buffer[1] == -115)
int element = 0; fixSlime (buffer);
for (int j = 0; j < 500; j++) image = new BufferedImage (70, 50, BufferedImage.TYPE_BYTE_GRAY); // width/height
{ DataBuffer db = image.getRaster ().getDataBuffer ();
int bits = buffer[j] & 0xFF; int element = 0;
for (int m = 0; m < 7; m++)
{ for (int j = 0; j < 500; j++)
if (bits == 0) {
{ int bits = buffer[j] & 0xFF;
element += 7 - m; for (int m = 0; m < 7; m++)
break; {
} if (bits == 0)
if ((bits & 1) == 1) {
db.setElem (element, 255); element += 7 - m;
bits >>= 1; break;
element++; }
} if ((bits & 1) == 1)
} db.setElem (element, 255);
} bits >>= 1;
element++;
private void fixSlime (byte[] buffer) }
{ }
for (int i = 0; i < 208; i++) }
buffer[i] = 0;
buffer[124] = -108; // ---------------------------------------------------------------------------------//
buffer[134] = -43; private void fixSlime (byte[] buffer)
buffer[135] = -128; // ---------------------------------------------------------------------------------//
buffer[144] = -44; {
buffer[145] = -126; for (int i = 0; i < 208; i++)
buffer[154] = -48; buffer[i] = 0;
buffer[155] = -118; buffer[124] = -108;
buffer[164] = -64; buffer[134] = -43;
buffer[165] = -86; buffer[135] = -128;
buffer[174] = -64; buffer[144] = -44;
buffer[175] = -86; buffer[145] = -126;
buffer[184] = -63; buffer[154] = -48;
buffer[185] = -86; buffer[155] = -118;
buffer[194] = -44; buffer[164] = -64;
buffer[195] = -86; buffer[165] = -86;
buffer[204] = -44; buffer[174] = -64;
buffer[205] = -126; buffer[175] = -86;
} buffer[184] = -63;
buffer[185] = -86;
buffer[194] = -44;
buffer[195] = -86;
buffer[204] = -44;
buffer[205] = -126;
}
} }

View File

@ -1,32 +1,36 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer; import java.awt.image.DataBuffer;
class ImageV2 extends AbstractImage // -----------------------------------------------------------------------------------//
{ class ImageV2 extends AbstractImage
public ImageV2 (String name, byte[] buffer) // -----------------------------------------------------------------------------------//
{ {
super (name, buffer); // ---------------------------------------------------------------------------------//
ImageV2 (String name, byte[] buffer)
image = new BufferedImage (70, 48, BufferedImage.TYPE_BYTE_GRAY); // width/height // ---------------------------------------------------------------------------------//
DataBuffer db = image.getRaster ().getDataBuffer (); {
int offset = 0; super (name, buffer);
int size = 7;
image = new BufferedImage (70, 48, BufferedImage.TYPE_BYTE_GRAY); // width/height
for (int i = 0; i < 6; i++) DataBuffer db = image.getRaster ().getDataBuffer ();
for (int j = 0; j < 10; j++) int offset = 0;
for (int k = 7; k >= 0; k--) int size = 7;
{
int element = i * 560 + j * 7 + k * 70; for (int i = 0; i < 6; i++)
int bits = buffer[offset++] & 0xFF; for (int j = 0; j < 10; j++)
for (int m = size - 1; m >= 0; m--) for (int k = 7; k >= 0; k--)
{ {
if ((bits & 1) == 1) int element = i * 560 + j * 7 + k * 70;
db.setElem (element, 255); int bits = buffer[offset++] & 0xFF;
bits >>= 1; for (int m = size - 1; m >= 0; m--)
element++; {
} if ((bits & 1) == 1)
} db.setElem (element, 255);
} bits >>= 1;
element++;
}
}
}
} }

View File

@ -1,141 +1,163 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
class Item extends AbstractFile implements Comparable<Item> // -----------------------------------------------------------------------------------//
{ class Item extends AbstractFile implements Comparable<Item>
public final int itemID; // -----------------------------------------------------------------------------------//
private final int type; {
private final long cost; public final int itemID;
public int partyOwns; private final int type;
String genericName; private final long cost;
static int counter = 0; public int partyOwns;
public final Dice damage; String genericName;
public final int armourClass; static int counter = 0;
public final int speed; public final Dice damage;
public final int armourClass;
public Item (String name, byte[] buffer) public final int speed;
{
super (name, buffer); // ---------------------------------------------------------------------------------//
itemID = counter++; Item (String name, byte[] buffer)
type = buffer[32]; // ---------------------------------------------------------------------------------//
cost = HexFormatter.intValue (buffer[44], buffer[45]) {
+ HexFormatter.intValue (buffer[46], buffer[47]) * 10000 super (name, buffer);
+ HexFormatter.intValue (buffer[48], buffer[49]) * 100000000L; itemID = counter++;
genericName = HexFormatter.getPascalString (buffer, 16); type = buffer[32];
damage = new Dice (buffer, 66); cost = HexFormatter.intValue (buffer[44], buffer[45])
armourClass = buffer[62]; + HexFormatter.intValue (buffer[46], buffer[47]) * 10000
speed = buffer[72]; + HexFormatter.intValue (buffer[48], buffer[49]) * 100000000L;
} genericName = HexFormatter.getPascalString (buffer, 16);
damage = new Dice (buffer, 66);
@Override armourClass = buffer[62];
public String getText () speed = buffer[72];
{ }
StringBuilder text = new StringBuilder ();
// ---------------------------------------------------------------------------------//
text.append ("Name ......... : " + name); @Override
// int length = HexFormatter.intValue (buffer[16]); public String getText ()
text.append ("\nGeneric name . : " + genericName); // ---------------------------------------------------------------------------------//
text.append ("\nType ......... : " + type); {
text.append ("\nCost ......... : " + cost); StringBuilder text = new StringBuilder ();
text.append ("\nArmour class . : " + armourClass);
text.append ("\nDamage ....... : " + damage); text.append ("Name ......... : " + name);
text.append ("\nSpeed ........ : " + speed); // int length = HexFormatter.intValue (buffer[16]);
text.append ("\nCursed? ...... : " + isCursed ()); text.append ("\nGeneric name . : " + genericName);
int stock = getStockOnHand (); text.append ("\nType ......... : " + type);
text.append ("\nStock on hand : " + stock); text.append ("\nCost ......... : " + cost);
if (stock < 0) text.append ("\nArmour class . : " + armourClass);
text.append (" (always in stock)"); text.append ("\nDamage ....... : " + damage);
text.append ("\nSpeed ........ : " + speed);
return text.toString (); text.append ("\nCursed? ...... : " + isCursed ());
} int stock = getStockOnHand ();
text.append ("\nStock on hand : " + stock);
public int getType () if (stock < 0)
{ text.append (" (always in stock)");
return type;
} return text.toString ();
}
// public int getArmourClass ()
// { // ---------------------------------------------------------------------------------//
// return buffer[62]; public int getType ()
// } // ---------------------------------------------------------------------------------//
{
// public int getSpeed () return type;
// { }
// return HexFormatter.intValue (buffer[72]);
// } // public int getArmourClass ()
// {
public long getCost () // return buffer[62];
{ // }
return cost;
} // public int getSpeed ()
// {
public boolean isCursed () // return HexFormatter.intValue (buffer[72]);
{ // }
return buffer[36] != 0;
} // ---------------------------------------------------------------------------------//
public long getCost ()
public int getStockOnHand () // ---------------------------------------------------------------------------------//
{ {
if (buffer[50] == -1 && buffer[51] == -1) return cost;
return -1; }
return HexFormatter.intValue (buffer[50], buffer[51]); // ---------------------------------------------------------------------------------//
} public boolean isCursed ()
// ---------------------------------------------------------------------------------//
public boolean canUse (int type2) {
{ return buffer[36] != 0;
int users = buffer[54] & 0xFF; }
return ((users >>> type2) & 1) == 1;
} // ---------------------------------------------------------------------------------//
public int getStockOnHand ()
@Override // ---------------------------------------------------------------------------------//
public String toString () {
{ if (buffer[50] == -1 && buffer[51] == -1)
StringBuilder line = new StringBuilder (); return -1;
line.append (String.format ("%-16s", name));
if (buffer[36] == -1) return HexFormatter.intValue (buffer[50], buffer[51]);
line.append ("(c) "); }
else
line.append (" "); // ---------------------------------------------------------------------------------//
line.append (String.format ("%02X ", buffer[62])); public boolean canUse (int type2)
line.append (String.format ("%02X ", buffer[34])); // ---------------------------------------------------------------------------------//
line.append (String.format ("%02X %02X", buffer[50], buffer[51])); {
int users = buffer[54] & 0xFF;
// if (buffer[50] == -1 && buffer[51] == -1) return ((users >>> type2) & 1) == 1;
// line.append ("* "); }
// else
// line.append (HexFormatter.intValue (buffer[50], buffer[51]) + " "); // ---------------------------------------------------------------------------------//
@Override
for (int i = 38; i < 44; i++) public String toString ()
line.append (HexFormatter.format2 (buffer[i]) + " "); // ---------------------------------------------------------------------------------//
for (int i = 48; i < 50; i++) {
line.append (HexFormatter.format2 (buffer[i]) + " "); StringBuilder line = new StringBuilder ();
for (int i = 52; i < 62; i++) line.append (String.format ("%-16s", name));
line.append (HexFormatter.format2 (buffer[i]) + " "); if (buffer[36] == -1)
// for (int i = 64; i < 78; i++) line.append ("(c) ");
// line.append (HexFormatter.format2 (buffer[i]) + " "); else
line.append (" ");
return line.toString (); line.append (String.format ("%02X ", buffer[62]));
} line.append (String.format ("%02X ", buffer[34]));
line.append (String.format ("%02X %02X", buffer[50], buffer[51]));
public String getDump (int block)
{ // if (buffer[50] == -1 && buffer[51] == -1)
StringBuilder line = new StringBuilder (String.format ("%3d %-16s", itemID, name)); // line.append ("* ");
int lo = block == 0 ? 32 : block == 1 ? 46 : 70; // else
int hi = lo + 24; // line.append (HexFormatter.intValue (buffer[50], buffer[51]) + " ");
if (hi > buffer.length)
hi = buffer.length; for (int i = 38; i < 44; i++)
for (int i = lo; i < hi; i++) line.append (HexFormatter.format2 (buffer[i]) + " ");
line.append (String.format ("%02X ", buffer[i])); for (int i = 48; i < 50; i++)
return line.toString (); line.append (HexFormatter.format2 (buffer[i]) + " ");
} for (int i = 52; i < 62; i++)
line.append (HexFormatter.format2 (buffer[i]) + " ");
@Override // for (int i = 64; i < 78; i++)
public int compareTo (Item otherItem) // line.append (HexFormatter.format2 (buffer[i]) + " ");
{
Item item = otherItem; return line.toString ();
return this.type - item.type; }
}
// ---------------------------------------------------------------------------------//
public String getDump (int block)
// ---------------------------------------------------------------------------------//
{
StringBuilder line = new StringBuilder (String.format ("%3d %-16s", itemID, name));
int lo = block == 0 ? 32 : block == 1 ? 46 : 70;
int hi = lo + 24;
if (hi > buffer.length)
hi = buffer.length;
for (int i = lo; i < hi; i++)
line.append (String.format ("%02X ", buffer[i]));
return line.toString ();
}
// ---------------------------------------------------------------------------------//
@Override
public int compareTo (Item otherItem)
// ---------------------------------------------------------------------------------//
{
Item item = otherItem;
return this.type - item.type;
}
} }

View File

@ -1,21 +1,27 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
class MazeAddress // -----------------------------------------------------------------------------------//
{ class MazeAddress
public final int level; // -----------------------------------------------------------------------------------//
public final int row; {
public final int column; public final int level;
public final int row;
public MazeAddress (int level, int row, int column) public final int column;
{
this.level = level; // ---------------------------------------------------------------------------------//
this.row = row; MazeAddress (int level, int row, int column)
this.column = column; // ---------------------------------------------------------------------------------//
} {
this.level = level;
@Override this.row = row;
public String toString () this.column = column;
{ }
return level + "/" + row + "/" + column;
} // ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
return level + "/" + row + "/" + column;
}
} }

View File

@ -1,328 +1,370 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.util.List; import java.util.List;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
class MazeCell // -----------------------------------------------------------------------------------//
{ class MazeCell
static Dimension cellSize = new Dimension (22, 22); // size in pixels // -----------------------------------------------------------------------------------//
{
boolean northWall; static Dimension cellSize = new Dimension (22, 22); // size in pixels
boolean southWall;
boolean eastWall; boolean northWall;
boolean westWall; boolean southWall;
boolean eastWall;
boolean northDoor; boolean westWall;
boolean southDoor;
boolean eastDoor; boolean northDoor;
boolean westDoor; boolean southDoor;
boolean eastDoor;
boolean darkness; boolean westDoor;
boolean stairs; boolean darkness;
boolean pit;
boolean spinner; boolean stairs;
boolean chute; boolean pit;
boolean elevator; boolean spinner;
boolean monsterLair; boolean chute;
boolean rock; boolean elevator;
boolean teleport; boolean monsterLair;
boolean spellsBlocked; boolean rock;
boolean teleport;
int elevatorFrom; boolean spellsBlocked;
int elevatorTo;
int elevatorFrom;
int messageType; int elevatorTo;
int monsterID = -1;
int itemID; int messageType;
int monsterID = -1;
int unknown; int itemID;
MazeAddress address; int unknown;
MazeAddress addressTo; // if teleport/stairs/chute
MazeAddress address;
public Message message; MazeAddress addressTo; // if teleport/stairs/chute
public List<Monster> monsters;
public Item itemRequired; public Message message;
public Item itemObtained; public List<Monster> monsters;
public Item itemRequired;
public MazeCell (MazeAddress address) public Item itemObtained;
{
this.address = address; // ---------------------------------------------------------------------------------//
} MazeCell (MazeAddress address)
// ---------------------------------------------------------------------------------//
public void draw (Graphics2D g, int x, int y) {
{ this.address = address;
g.setColor (Color.BLACK); }
g.fillRect (x, y, 22, 22);
// ---------------------------------------------------------------------------------//
g.setColor (Color.WHITE); void draw (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
if (westWall) {
drawWest (g, x, y); g.setColor (Color.BLACK);
if (eastWall) g.fillRect (x, y, 22, 22);
drawEast (g, x, y);
if (northWall) g.setColor (Color.WHITE);
drawNorth (g, x, y);
if (southWall) if (westWall)
drawSouth (g, x, y); drawWest (g, x, y);
if (eastWall)
g.setColor (Color.RED); drawEast (g, x, y);
if (northWall)
if (westDoor) drawNorth (g, x, y);
drawWest (g, x, y); if (southWall)
if (eastDoor) drawSouth (g, x, y);
drawEast (g, x, y);
if (northDoor) g.setColor (Color.RED);
drawNorth (g, x, y);
if (southDoor) if (westDoor)
drawSouth (g, x, y); drawWest (g, x, y);
if (eastDoor)
g.setColor (Color.GREEN); drawEast (g, x, y);
if (northDoor)
if (westDoor && westWall) drawNorth (g, x, y);
drawWest (g, x, y); if (southDoor)
if (eastDoor && eastWall) drawSouth (g, x, y);
drawEast (g, x, y);
if (northDoor && northWall) g.setColor (Color.GREEN);
drawNorth (g, x, y);
if (southDoor && southWall) if (westDoor && westWall)
drawSouth (g, x, y); drawWest (g, x, y);
if (eastDoor && eastWall)
g.setColor (Color.WHITE); drawEast (g, x, y);
if (northDoor && northWall)
if (monsterLair) drawNorth (g, x, y);
drawMonsterLair (g, x, y); if (southDoor && southWall)
drawSouth (g, x, y);
if (stairs)
if (address.level < addressTo.level) g.setColor (Color.WHITE);
drawStairsDown (g, x, y);
else if (monsterLair)
drawStairsUp (g, x, y); drawMonsterLair (g, x, y);
else if (message != null)
drawChar (g, x, y, "M", Color.RED); if (stairs)
else if (pit) if (address.level < addressTo.level)
drawPit (g, x, y); drawStairsDown (g, x, y);
else if (chute) else
drawChute (g, x, y); drawStairsUp (g, x, y);
else if (spinner) else if (message != null)
g.drawString ("S", x + 8, y + 16); drawChar (g, x, y, "M", Color.RED);
else if (teleport) else if (pit)
drawTeleport (g, x, y); drawPit (g, x, y);
else if (darkness) else if (chute)
drawDarkness (g, x, y); drawChute (g, x, y);
else if (rock) else if (spinner)
drawRock (g, x, y); g.drawString ("S", x + 8, y + 16);
else if (elevator) else if (teleport)
drawElevator (g, x, y, (elevatorTo - elevatorFrom + 1) / 2); drawTeleport (g, x, y);
else if (monsterID >= 0) else if (darkness)
drawMonster (g, x, y); drawDarkness (g, x, y);
else if (spellsBlocked) else if (rock)
drawSpellsBlocked (g, x, y); drawRock (g, x, y);
else if (unknown != 0) else if (elevator)
drawChar (g, x, y, HexFormatter.format1 (unknown), Color.GRAY); drawElevator (g, x, y, (elevatorTo - elevatorFrom + 1) / 2);
} else if (monsterID >= 0)
drawMonster (g, x, y);
public void drawWest (Graphics2D g, int x, int y) else if (spellsBlocked)
{ drawSpellsBlocked (g, x, y);
g.drawLine (x + 1, y + 1, x + 1, y + cellSize.height - 1); else if (unknown != 0)
} drawChar (g, x, y, HexFormatter.format1 (unknown), Color.GRAY);
}
private void drawEast (Graphics2D g, int x, int y)
{ // ---------------------------------------------------------------------------------//
g.drawLine (x + cellSize.width - 1, y + 1, x + cellSize.width - 1, void drawWest (Graphics2D g, int x, int y)
y + cellSize.height - 1); // ---------------------------------------------------------------------------------//
} {
g.drawLine (x + 1, y + 1, x + 1, y + cellSize.height - 1);
private void drawNorth (Graphics2D g, int x, int y) }
{
g.drawLine (x + 1, y + 1, x + cellSize.width - 1, y + 1); // ---------------------------------------------------------------------------------//
} void drawEast (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
private void drawSouth (Graphics2D g, int x, int y) {
{ g.drawLine (x + cellSize.width - 1, y + 1, x + cellSize.width - 1,
g.drawLine (x + 1, y + cellSize.height - 1, x + cellSize.width - 1, y + cellSize.height - 1);
y + cellSize.height - 1); }
}
// ---------------------------------------------------------------------------------//
public void drawStairsUp (Graphics2D g, int x, int y) void drawNorth (Graphics2D g, int x, int y)
{ // ---------------------------------------------------------------------------------//
g.drawLine (x + 6, y + 18, x + 6, y + 14); {
g.drawLine (x + 6, y + 14, x + 10, y + 14); g.drawLine (x + 1, y + 1, x + cellSize.width - 1, y + 1);
g.drawLine (x + 10, y + 14, x + 10, y + 10); }
g.drawLine (x + 10, y + 10, x + 14, y + 10);
g.drawLine (x + 14, y + 10, x + 14, y + 6); // ---------------------------------------------------------------------------------//
g.drawLine (x + 14, y + 6, x + 18, y + 6); void drawSouth (Graphics2D g, int x, int y)
} // ---------------------------------------------------------------------------------//
{
public void drawStairsDown (Graphics2D g, int x, int y) g.drawLine (x + 1, y + cellSize.height - 1, x + cellSize.width - 1,
{ y + cellSize.height - 1);
g.drawLine (x + 4, y + 7, x + 8, y + 7); }
g.drawLine (x + 8, y + 7, x + 8, y + 11);
g.drawLine (x + 8, y + 11, x + 12, y + 11); // ---------------------------------------------------------------------------------//
g.drawLine (x + 12, y + 11, x + 12, y + 15); void drawStairsUp (Graphics2D g, int x, int y)
g.drawLine (x + 12, y + 15, x + 16, y + 15); // ---------------------------------------------------------------------------------//
g.drawLine (x + 16, y + 15, x + 16, y + 19); {
} g.drawLine (x + 6, y + 18, x + 6, y + 14);
g.drawLine (x + 6, y + 14, x + 10, y + 14);
public void drawPit (Graphics2D g, int x, int y) g.drawLine (x + 10, y + 14, x + 10, y + 10);
{ g.drawLine (x + 10, y + 10, x + 14, y + 10);
g.drawLine (x + 5, y + 14, x + 5, y + 19); g.drawLine (x + 14, y + 10, x + 14, y + 6);
g.drawLine (x + 5, y + 19, x + 17, y + 19); g.drawLine (x + 14, y + 6, x + 18, y + 6);
g.drawLine (x + 17, y + 14, x + 17, y + 19); }
}
// ---------------------------------------------------------------------------------//
public void drawChute (Graphics2D g, int x, int y) void drawStairsDown (Graphics2D g, int x, int y)
{ // ---------------------------------------------------------------------------------//
g.drawLine (x + 6, y + 6, x + 10, y + 6); {
g.drawLine (x + 10, y + 6, x + 18, y + 18); g.drawLine (x + 4, y + 7, x + 8, y + 7);
} g.drawLine (x + 8, y + 7, x + 8, y + 11);
g.drawLine (x + 8, y + 11, x + 12, y + 11);
public void drawElevator (Graphics2D g, int x, int y, int rows) g.drawLine (x + 12, y + 11, x + 12, y + 15);
{ g.drawLine (x + 12, y + 15, x + 16, y + 15);
for (int i = 0; i < rows; i++) g.drawLine (x + 16, y + 15, x + 16, y + 19);
{ }
g.drawOval (x + 7, y + i * 5 + 5, 2, 2);
g.drawOval (x + 14, y + i * 5 + 5, 2, 2); // ---------------------------------------------------------------------------------//
} void drawPit (Graphics2D g, int x, int y)
} // ---------------------------------------------------------------------------------//
{
public void drawMonsterLair (Graphics2D g, int x, int y) g.drawLine (x + 5, y + 14, x + 5, y + 19);
{ g.drawLine (x + 5, y + 19, x + 17, y + 19);
g.setColor (Color.YELLOW); g.drawLine (x + 17, y + 14, x + 17, y + 19);
g.fillOval (x + 4, y + 4, 2, 2); }
g.setColor (Color.WHITE);
} // ---------------------------------------------------------------------------------//
void drawChute (Graphics2D g, int x, int y)
public void drawTeleport (Graphics2D g, int x, int y) // ---------------------------------------------------------------------------------//
{ {
g.setColor (Color.GREEN); g.drawLine (x + 6, y + 6, x + 10, y + 6);
g.fillOval (x + 8, y + 8, 8, 8); g.drawLine (x + 10, y + 6, x + 18, y + 18);
g.setColor (Color.WHITE); }
}
// ---------------------------------------------------------------------------------//
public void drawSpellsBlocked (Graphics2D g, int x, int y) void drawElevator (Graphics2D g, int x, int y, int rows)
{ // ---------------------------------------------------------------------------------//
g.setColor (Color.YELLOW); {
g.fillOval (x + 8, y + 8, 8, 8); for (int i = 0; i < rows; i++)
g.setColor (Color.WHITE); {
} g.drawOval (x + 7, y + i * 5 + 5, 2, 2);
g.drawOval (x + 14, y + i * 5 + 5, 2, 2);
public void drawMonster (Graphics2D g, int x, int y) }
{ }
g.setColor (Color.RED);
g.fillOval (x + 8, y + 8, 8, 8); // ---------------------------------------------------------------------------------//
g.setColor (Color.WHITE); void drawMonsterLair (Graphics2D g, int x, int y)
} // ---------------------------------------------------------------------------------//
{
public void drawDarkness (Graphics2D g, int x, int y) g.setColor (Color.YELLOW);
{ g.fillOval (x + 4, y + 4, 2, 2);
g.setColor (Color.gray); g.setColor (Color.WHITE);
for (int h = 0; h < 15; h += 7) }
for (int offset = 0; offset < 15; offset += 7)
g.drawOval (x + offset + 4, y + h + 4, 1, 1); // ---------------------------------------------------------------------------------//
g.setColor (Color.white); void drawTeleport (Graphics2D g, int x, int y)
} // ---------------------------------------------------------------------------------//
{
public void drawRock (Graphics2D g, int x, int y) g.setColor (Color.GREEN);
{ g.fillOval (x + 8, y + 8, 8, 8);
for (int h = 0; h < 15; h += 7) g.setColor (Color.WHITE);
for (int offset = 0; offset < 15; offset += 7) }
g.drawOval (x + offset + 4, y + h + 4, 1, 1);
} // ---------------------------------------------------------------------------------//
void drawSpellsBlocked (Graphics2D g, int x, int y)
public void drawChar (Graphics2D g, int x, int y, String c, Color colour) // ---------------------------------------------------------------------------------//
{ {
g.setColor (colour); g.setColor (Color.YELLOW);
g.fillRect (x + 7, y + 6, 11, 11); g.fillOval (x + 8, y + 8, 8, 8);
g.setColor (Color.WHITE); g.setColor (Color.WHITE);
g.drawString (c, x + 8, y + 16); }
}
// ---------------------------------------------------------------------------------//
public void drawHotDogStand (Graphics2D g, int x, int y) void drawMonster (Graphics2D g, int x, int y)
{ // ---------------------------------------------------------------------------------//
g.drawRect (x + 5, y + 11, 12, 6); {
g.drawOval (x + 6, y + 18, 3, 3); g.setColor (Color.RED);
g.drawOval (x + 13, y + 18, 3, 3); g.fillOval (x + 8, y + 8, 8, 8);
g.drawLine (x + 8, y + 6, x + 8, y + 10); g.setColor (Color.WHITE);
g.drawLine (x + 14, y + 6, x + 14, y + 10); }
g.drawLine (x + 5, y + 5, x + 17, y + 5);
} // ---------------------------------------------------------------------------------//
void drawDarkness (Graphics2D g, int x, int y)
public String getTooltipText () // ---------------------------------------------------------------------------------//
{ {
StringBuilder sign = new StringBuilder ("<html><pre>"); g.setColor (Color.gray);
sign.append ("&nbsp;<b>"); for (int h = 0; h < 15; h += 7)
sign.append (address.row + "N "); for (int offset = 0; offset < 15; offset += 7)
sign.append (address.column + "E</b>&nbsp;<br>"); g.drawOval (x + offset + 4, y + h + 4, 1, 1);
g.setColor (Color.white);
if (message != null) }
sign.append (message.toHTMLString ());
// ---------------------------------------------------------------------------------//
if (elevator) void drawRock (Graphics2D g, int x, int y)
sign.append ("&nbsp;Elevator: L" + elevatorFrom + "-L" + elevatorTo + "&nbsp;"); // ---------------------------------------------------------------------------------//
if (stairs) {
{ for (int h = 0; h < 15; h += 7)
sign.append ("&nbsp;Stairs to "); for (int offset = 0; offset < 15; offset += 7)
if (addressTo.level == 0) g.drawOval (x + offset + 4, y + h + 4, 1, 1);
sign.append ("castle&nbsp;"); }
else
{ // ---------------------------------------------------------------------------------//
sign.append ("level " + addressTo.level + "&nbsp;"); void drawChar (Graphics2D g, int x, int y, String c, Color colour)
} // ---------------------------------------------------------------------------------//
} {
if (teleport) g.setColor (colour);
{ g.fillRect (x + 7, y + 6, 11, 11);
sign.append ("&nbsp;Teleport to "); g.setColor (Color.WHITE);
if (addressTo.level == 0) g.drawString (c, x + 8, y + 16);
sign.append ("castle&nbsp;"); }
else
{ // ---------------------------------------------------------------------------------//
sign.append ("L" + addressTo.level + " " + addressTo.row + "N " + addressTo.column void drawHotDogStand (Graphics2D g, int x, int y)
+ "E&nbsp;"); // ---------------------------------------------------------------------------------//
} {
} g.drawRect (x + 5, y + 11, 12, 6);
if (pit) g.drawOval (x + 6, y + 18, 3, 3);
sign.append ("&nbsp;Pit"); g.drawOval (x + 13, y + 18, 3, 3);
if (spinner) g.drawLine (x + 8, y + 6, x + 8, y + 10);
sign.append ("&nbsp;Spinner&nbsp;"); g.drawLine (x + 14, y + 6, x + 14, y + 10);
if (chute) g.drawLine (x + 5, y + 5, x + 17, y + 5);
sign.append ("&nbsp;Chute"); }
if (darkness)
sign.append ("&nbsp;Darkness&nbsp;"); // ---------------------------------------------------------------------------------//
if (rock) String getTooltipText ()
sign.append ("&nbsp;Rock&nbsp;"); // ---------------------------------------------------------------------------------//
if (spellsBlocked) {
sign.append ("&nbsp;Spells fizzle out&nbsp;"); StringBuilder sign = new StringBuilder ("<html><pre>");
if (monsterID >= 0) sign.append ("&nbsp;<b>");
if (monsters == null || monsterID >= monsters.size ()) sign.append (address.row + "N ");
sign.append ("&nbsp;Monster&nbsp;"); sign.append (address.column + "E</b>&nbsp;<br>");
else
{ if (message != null)
Monster monster = monsters.get (monsterID); sign.append (message.toHTMLString ());
sign.append ("&nbsp;<b>" + monster.getRealName () + "&nbsp;</b>");
while (monster.partnerOdds == 100) if (elevator)
{ sign.append ("&nbsp;Elevator: L" + elevatorFrom + "-L" + elevatorTo + "&nbsp;");
monster = monsters.get (monster.partnerID); if (stairs)
sign.append ("<br>&nbsp;<b>" + monster.getRealName () + "&nbsp;</b>"); {
} sign.append ("&nbsp;Stairs to ");
} if (addressTo.level == 0)
if (itemRequired != null) sign.append ("castle&nbsp;");
{ else
sign.append ("&nbsp;<b>Requires: "); {
sign.append (itemRequired.getName () + "&nbsp;</b>"); sign.append ("level " + addressTo.level + "&nbsp;");
} }
}
if (itemObtained != null) if (teleport)
{ {
sign.append ("&nbsp;<b>Obtain: "); sign.append ("&nbsp;Teleport to ");
sign.append (itemObtained.getName () + "&nbsp;</b>"); if (addressTo.level == 0)
} sign.append ("castle&nbsp;");
sign.append ("</pre></html>"); else
return sign.toString (); {
} sign.append ("L" + addressTo.level + " " + addressTo.row + "N " + addressTo.column
+ "E&nbsp;");
}
}
if (pit)
sign.append ("&nbsp;Pit");
if (spinner)
sign.append ("&nbsp;Spinner&nbsp;");
if (chute)
sign.append ("&nbsp;Chute");
if (darkness)
sign.append ("&nbsp;Darkness&nbsp;");
if (rock)
sign.append ("&nbsp;Rock&nbsp;");
if (spellsBlocked)
sign.append ("&nbsp;Spells fizzle out&nbsp;");
if (monsterID >= 0)
if (monsters == null || monsterID >= monsters.size ())
sign.append ("&nbsp;Monster&nbsp;");
else
{
Monster monster = monsters.get (monsterID);
sign.append ("&nbsp;<b>" + monster.getRealName () + "&nbsp;</b>");
while (monster.partnerOdds == 100)
{
monster = monsters.get (monster.partnerID);
sign.append ("<br>&nbsp;<b>" + monster.getRealName () + "&nbsp;</b>");
}
}
if (itemRequired != null)
{
sign.append ("&nbsp;<b>Requires: ");
sign.append (itemRequired.getName () + "&nbsp;</b>");
}
if (itemObtained != null)
{
sign.append ("&nbsp;<b>Obtain: ");
sign.append (itemObtained.getName () + "&nbsp;</b>");
}
sign.append ("</pre></html>");
return sign.toString ();
}
} }

View File

@ -12,7 +12,9 @@ import com.bytezone.common.Utility;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
public class MazeGridV5 extends AbstractFile // -----------------------------------------------------------------------------------//
class MazeGridV5 extends AbstractFile
// -----------------------------------------------------------------------------------//
{ {
private final MessageBlock messageBlock; private final MessageBlock messageBlock;
List<MazeGrid> grids = new ArrayList<> (); List<MazeGrid> grids = new ArrayList<> ();
@ -21,7 +23,9 @@ public class MazeGridV5 extends AbstractFile
int maxX = 0; int maxX = 0;
int maxY = 0; int maxY = 0;
public MazeGridV5 (String name, byte[] buffer, MessageBlock messageBlock) // ---------------------------------------------------------------------------------//
MazeGridV5 (String name, byte[] buffer, MessageBlock messageBlock)
// ---------------------------------------------------------------------------------//
{ {
super (name, buffer); super (name, buffer);
@ -45,8 +49,10 @@ public class MazeGridV5 extends AbstractFile
} }
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public BufferedImage getImage () public BufferedImage getImage ()
// ---------------------------------------------------------------------------------//
{ {
Dimension cellSize = new Dimension (22, 22); Dimension cellSize = new Dimension (22, 22);
int fudge = 30; int fudge = 30;
@ -80,7 +86,9 @@ public class MazeGridV5 extends AbstractFile
return image; return image;
} }
// ---------------------------------------------------------------------------------//
private MazeCell getLayout (int gridNo, int row, int column) private MazeCell getLayout (int gridNo, int row, int column)
// ---------------------------------------------------------------------------------//
{ {
MazeAddress address = new MazeAddress (0, row, column); MazeAddress address = new MazeAddress (0, row, column);
MazeCell cell = new MazeCell (address); MazeCell cell = new MazeCell (address);
@ -103,8 +111,10 @@ public class MazeGridV5 extends AbstractFile
return cell; return cell;
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public String getHexDump () public String getHexDump ()
// ---------------------------------------------------------------------------------//
{ {
StringBuilder text = new StringBuilder (super.getHexDump ()); StringBuilder text = new StringBuilder (super.getHexDump ());
@ -187,7 +197,9 @@ public class MazeGridV5 extends AbstractFile
return text.toString (); return text.toString ();
} }
// ---------------------------------------------------------------------------------//
private class MazeGrid private class MazeGrid
// ---------------------------------------------------------------------------------//
{ {
MazeCell[][] grid; MazeCell[][] grid;
int xOffset; int xOffset;

File diff suppressed because it is too large Load Diff

View File

@ -1,71 +1,85 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
abstract class Message extends AbstractFile // -----------------------------------------------------------------------------------//
{ abstract class Message extends AbstractFile
private static int nextId = 0; // -----------------------------------------------------------------------------------//
protected String message; {
private final int id; private static int nextId = 0;
private int totalLines; protected String message;
List<String> lines = new ArrayList<> (); private final int id;
private int totalLines;
public Message (byte[] buffer) List<String> lines = new ArrayList<> ();
{
super ("Message " + nextId, buffer); // ---------------------------------------------------------------------------------//
this.id = nextId; Message (byte[] buffer)
// ---------------------------------------------------------------------------------//
int recordLength = 42; {
StringBuilder text = new StringBuilder (); super ("Message " + nextId, buffer);
this.id = nextId;
for (int ptr = 0; ptr < buffer.length; ptr += recordLength)
{ int recordLength = 42;
nextId++; StringBuilder text = new StringBuilder ();
totalLines++;
String line = getLine (ptr); for (int ptr = 0; ptr < buffer.length; ptr += recordLength)
text.append (line + "\n"); {
lines.add (line); nextId++;
} totalLines++;
text.deleteCharAt (text.length () - 1); String line = getLine (ptr);
message = text.toString (); text.append (line + "\n");
} lines.add (line);
}
protected abstract String getLine (int offset); text.deleteCharAt (text.length () - 1);
message = text.toString ();
public boolean match (int messageNum) }
{
if (id == messageNum) // ---------------------------------------------------------------------------------//
return true; protected abstract String getLine (int offset);
// ---------------------------------------------------------------------------------//
// this code is to allow for a bug in scenario #1
if (messageNum > id && messageNum < (id + totalLines)) // ---------------------------------------------------------------------------------//
return true; public boolean match (int messageNum)
// ---------------------------------------------------------------------------------//
return false; {
} if (id == messageNum)
return true;
@Override
public String getText () // this code is to allow for a bug in scenario #1
{ if (messageNum > id && messageNum < (id + totalLines))
return message; return true;
}
return false;
public String toHTMLString () }
{
StringBuilder message = new StringBuilder (); // ---------------------------------------------------------------------------------//
for (String line : lines) @Override
message.append ("&nbsp;" + line + "&nbsp;<br>"); public String getText ()
if (message.length () > 0) // ---------------------------------------------------------------------------------//
for (int i = 0; i < 4; i++) {
message.deleteCharAt (message.length () - 1); // remove <br> tag return message;
return message.toString (); }
}
// ---------------------------------------------------------------------------------//
public static void resetMessageId () public String toHTMLString ()
{ // ---------------------------------------------------------------------------------//
nextId = 0; {
} StringBuilder message = new StringBuilder ();
for (String line : lines)
message.append ("&nbsp;" + line + "&nbsp;<br>");
if (message.length () > 0)
for (int i = 0; i < 4; i++)
message.deleteCharAt (message.length () - 1); // remove <br> tag
return message.toString ();
}
// ---------------------------------------------------------------------------------//
public static void resetMessageId ()
// ---------------------------------------------------------------------------------//
{
nextId = 0;
}
} }

View File

@ -7,7 +7,9 @@ import java.util.List;
import com.bytezone.common.Utility; import com.bytezone.common.Utility;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
public class MessageBlock extends AbstractFile implements Iterable<MessageDataBlock> // -----------------------------------------------------------------------------------//
class MessageBlock extends AbstractFile implements Iterable<MessageDataBlock>
// -----------------------------------------------------------------------------------//
{ {
private final int indexOffset; private final int indexOffset;
private final int indexLength; private final int indexLength;
@ -15,7 +17,9 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
private final List<MessageDataBlock> messageDataBlocks = new ArrayList<> (); private final List<MessageDataBlock> messageDataBlocks = new ArrayList<> ();
public MessageBlock (byte[] buffer, Huffman huffman) // ---------------------------------------------------------------------------------//
MessageBlock (byte[] buffer, Huffman huffman)
// ---------------------------------------------------------------------------------//
{ {
super ("bollocks", buffer); super ("bollocks", buffer);
@ -35,7 +39,9 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
} }
} }
// ---------------------------------------------------------------------------------//
public String getMessageText (int messageNo) public String getMessageText (int messageNo)
// ---------------------------------------------------------------------------------//
{ {
for (int i = 0; i < messageDataBlocks.size (); i++) for (int i = 0; i < messageDataBlocks.size (); i++)
{ {
@ -46,7 +52,9 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
return null; return null;
} }
// ---------------------------------------------------------------------------------//
public List<String> getMessageLines (int messageNo) public List<String> getMessageLines (int messageNo)
// ---------------------------------------------------------------------------------//
{ {
List<String> lines = new ArrayList<> (); List<String> lines = new ArrayList<> ();
@ -72,7 +80,9 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
return lines; return lines;
} }
// ---------------------------------------------------------------------------------//
public byte[] getMessage (int messageNo) public byte[] getMessage (int messageNo)
// ---------------------------------------------------------------------------------//
{ {
for (int i = 0; i < messageDataBlocks.size (); i++) for (int i = 0; i < messageDataBlocks.size (); i++)
{ {
@ -83,8 +93,10 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
return null; return null;
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public String getText () public String getText ()
// ---------------------------------------------------------------------------------//
{ {
if (text != null) if (text != null)
return text; return text;
@ -102,8 +114,10 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
return this.text; return this.text;
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public Iterator<MessageDataBlock> iterator () public Iterator<MessageDataBlock> iterator ()
// ---------------------------------------------------------------------------------//
{ {
return messageDataBlocks.iterator (); return messageDataBlocks.iterator ();
} }

View File

@ -6,7 +6,9 @@ import java.util.List;
import com.bytezone.common.Utility; import com.bytezone.common.Utility;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
public class MessageDataBlock extends AbstractFile // -----------------------------------------------------------------------------------//
class MessageDataBlock extends AbstractFile
// -----------------------------------------------------------------------------------//
{ {
final int firstMessageNo; final int firstMessageNo;
final int lastMessageNo; final int lastMessageNo;
@ -16,8 +18,9 @@ public class MessageDataBlock extends AbstractFile
private final Huffman huffman; private final Huffman huffman;
public MessageDataBlock (String name, byte[] buffer, int firstMessageNo, // ---------------------------------------------------------------------------------//
Huffman huffman) MessageDataBlock (String name, byte[] buffer, int firstMessageNo, Huffman huffman)
// ---------------------------------------------------------------------------------//
{ {
super (name, buffer); super (name, buffer);
@ -75,7 +78,9 @@ public class MessageDataBlock extends AbstractFile
this.name += " - " + lastMessageNo; this.name += " - " + lastMessageNo;
} }
// ---------------------------------------------------------------------------------//
byte[] getMessage (int messageNo) byte[] getMessage (int messageNo)
// ---------------------------------------------------------------------------------//
{ {
for (Message message : messages) for (Message message : messages)
if (message.msgNo == messageNo) if (message.msgNo == messageNo)
@ -87,7 +92,9 @@ public class MessageDataBlock extends AbstractFile
return null; return null;
} }
// ---------------------------------------------------------------------------------//
String getText (int messageNo) String getText (int messageNo)
// ---------------------------------------------------------------------------------//
{ {
for (Message message : messages) for (Message message : messages)
if (message.msgNo == messageNo) if (message.msgNo == messageNo)
@ -99,8 +106,10 @@ public class MessageDataBlock extends AbstractFile
return null; return null;
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public String getText () public String getText ()
// ---------------------------------------------------------------------------------//
{ {
if (messages.size () == 0) if (messages.size () == 0)
return "No Messages"; return "No Messages";
@ -128,8 +137,10 @@ public class MessageDataBlock extends AbstractFile
return text.toString (); return text.toString ();
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public String toString () public String toString ()
// ---------------------------------------------------------------------------------//
{ {
StringBuilder text = new StringBuilder (); StringBuilder text = new StringBuilder ();
@ -145,7 +156,9 @@ public class MessageDataBlock extends AbstractFile
return text.toString (); return text.toString ();
} }
// ---------------------------------------------------------------------------------//
class Message class Message
// ---------------------------------------------------------------------------------//
{ {
final int msgNo; final int msgNo;
final int offset; final int offset;

View File

@ -1,284 +1,309 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
class Monster extends AbstractFile implements Comparable<Monster> // -----------------------------------------------------------------------------------//
{ class Monster extends AbstractFile implements Comparable<Monster>
public final String genericName; // -----------------------------------------------------------------------------------//
public final String realName; {
public final int monsterID; public final String genericName;
List<Monster> monsters; public final String realName;
Reward goldReward; public final int monsterID;
Reward chestReward; List<Monster> monsters;
Reward goldReward;
public final int type; Reward chestReward;
public final int imageID;
int rewardTable1; public final int type;
int rewardTable2; public final int imageID;
public final int partnerID; int rewardTable1;
public final int partnerOdds; int rewardTable2;
public final int armourClass; public final int partnerID;
public final int speed; public final int partnerOdds;
public final int mageSpellLevel; public final int armourClass;
public final int priestSpellLevel; public final int speed;
int levelDrain; public final int mageSpellLevel;
int bonus1; public final int priestSpellLevel;
int bonus2; int levelDrain;
int bonus3; int bonus1;
int resistance; int bonus2;
int abilities; int bonus3;
public final Dice groupSize, hitPoints; int resistance;
List<Dice> damage = new ArrayList<> (); int abilities;
public final Dice groupSize, hitPoints;
static int counter = 0; List<Dice> damage = new ArrayList<> ();
static boolean debug = true;
static int[] pwr = { 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 0, 0, 0, 0, 0 }; static int counter = 0;
static int[] weight1 = { 0, 1, 2, 4, 8, 16, 32, 64, 253, 506, 0 }; static boolean debug = true;
static int[] weight2 = { 0, 60, 120, 180, 300, 540, 1020, 0 }; static int[] pwr = { 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 0, 0, 0, 0, 0 };
static int[] weight1 = { 0, 1, 2, 4, 8, 16, 32, 64, 253, 506, 0 };
public static String[] monsterClass = static int[] weight2 = { 0, 60, 120, 180, 300, 540, 1020, 0 };
{ "Fighter", "Mage", "Priest", "Thief", "Midget", "Giant", "Mythical", "Dragon",
"Animal", "Were", "Undead", "Demon", "Insect", "Enchanted" }; public static String[] monsterClass =
{ "Fighter", "Mage", "Priest", "Thief", "Midget", "Giant", "Mythical", "Dragon",
private static int[] experience = { 55, 235, 415, 230, 380, 620, 840, 520, 550, 350, // 00-09 "Animal", "Were", "Undead", "Demon", "Insect", "Enchanted" };
475, 515, 920, 600, 735, 520, 795, 780, 990, 795, // 10-19
1360, 1320, 1275, 680, 960, 600, 755, 1120, 2075, private static int[] experience = { 55, 235, 415, 230, 380, 620, 840, 520, 550, 350, // 00-09
870, // 20-29 475, 515, 920, 600, 735, 520, 795, 780, 990, 795, // 10-19
960, 1120, 1120, 2435, 1080, 2280, 975, 875, 1135, 1360, 1320, 1275, 680, 960, 600, 755, 1120, 2075,
1200, // 30-39 870, // 20-29
620, 740, 1460, 1245, 960, 1405, 1040, 1220, 1520, 960, 1120, 1120, 2435, 1080, 2280, 975, 875, 1135,
1000, // 40-49 1200, // 30-39
960, 2340, 2160, 2395, 790, 1140, 1235, 1790, 1720, 620, 740, 1460, 1245, 960, 1405, 1040, 1220, 1520,
2240, // 50-59 1000, // 40-49
1475, 1540, 1720, 1900, 1240, 1220, 1020, 20435, 960, 2340, 2160, 2395, 790, 1140, 1235, 1790, 1720,
5100, 3515, // 60-69 2240, // 50-59
2115, 2920, 2060, 2140, 1400, 1640, 1280, 4450, 1475, 1540, 1720, 1900, 1240, 1220, 1020, 20435,
42840, 3300, // 70-79 5100, 3515, // 60-69
40875, 5000, 3300, 2395, 1935, 1600, 3330, 44090, 2115, 2920, 2060, 2140, 1400, 1640, 1280, 4450,
40840, 5200, // 80-89 42840, 3300, // 70-79
4155, 3000, 9200, 3160, 7460, 7320, 15880, 1600, 40875, 5000, 3300, 2395, 1935, 1600, 3330, 44090,
2200, 1000, 1900 // 90-100 40840, 5200, // 80-89
}; 4155, 3000, 9200, 3160, 7460, 7320, 15880, 1600,
2200, 1000, 1900 // 90-100
public Monster (String name, byte[] buffer, List<Reward> rewards, };
List<Monster> monsters)
{ // ---------------------------------------------------------------------------------//
super (name, buffer); Monster (String name, byte[] buffer, List<Reward> rewards, List<Monster> monsters)
// ---------------------------------------------------------------------------------//
realName = name; {
genericName = HexFormatter.getPascalString (buffer, 0); super (name, buffer);
this.monsterID = counter++;
this.monsters = monsters; realName = name;
goldReward = rewards.get (buffer[136]); genericName = HexFormatter.getPascalString (buffer, 0);
chestReward = rewards.get (buffer[138]); this.monsterID = counter++;
goldReward.addMonster (this, 0); this.monsters = monsters;
chestReward.addMonster (this, 1); goldReward = rewards.get (buffer[136]);
chestReward = rewards.get (buffer[138]);
imageID = buffer[64]; goldReward.addMonster (this, 0);
type = buffer[78]; chestReward.addMonster (this, 1);
armourClass = buffer[80];
speed = buffer[82]; imageID = buffer[64];
levelDrain = buffer[132]; type = buffer[78];
bonus1 = buffer[134]; armourClass = buffer[80];
rewardTable1 = buffer[136]; speed = buffer[82];
rewardTable2 = buffer[138]; levelDrain = buffer[132];
partnerID = buffer[140]; bonus1 = buffer[134];
partnerOdds = buffer[142]; rewardTable1 = buffer[136];
mageSpellLevel = buffer[144]; rewardTable2 = buffer[138];
priestSpellLevel = buffer[146]; partnerID = buffer[140];
bonus2 = buffer[150]; partnerOdds = buffer[142];
bonus3 = buffer[152]; mageSpellLevel = buffer[144];
resistance = buffer[154]; priestSpellLevel = buffer[146];
abilities = buffer[156]; bonus2 = buffer[150];
groupSize = new Dice (buffer, 66); bonus3 = buffer[152];
hitPoints = new Dice (buffer, 72); resistance = buffer[154];
abilities = buffer[156];
for (int i = 0, ptr = 84; i < 8; i++, ptr += 6) groupSize = new Dice (buffer, 66);
{ hitPoints = new Dice (buffer, 72);
if (buffer[ptr] == 0)
break; for (int i = 0, ptr = 84; i < 8; i++, ptr += 6)
damage.add (new Dice (buffer, ptr)); {
} if (buffer[ptr] == 0)
} break;
damage.add (new Dice (buffer, ptr));
@Override }
public String getText () }
{
StringBuilder text = new StringBuilder (); // ---------------------------------------------------------------------------------//
@Override
// these values definitely affect the damage a monster does (when breathing?) public String getText ()
int exp2 = ((buffer[72] & 0xFF) * (buffer[74] & 0xFF) - 1) * 20; // ---------------------------------------------------------------------------------//
int exp3 = weight2[speed]; // 1-6 {
int exp4 = (10 - armourClass) * 40; StringBuilder text = new StringBuilder ();
int exp5 = getBonus (35, mageSpellLevel);
int exp6 = getBonus (35, priestSpellLevel); // these values definitely affect the damage a monster does (when breathing?)
int exp10 = getBonus (200, levelDrain); int exp2 = ((buffer[72] & 0xFF) * (buffer[74] & 0xFF) - 1) * 20;
int exp8 = getBonus (90, bonus1); int exp3 = weight2[speed]; // 1-6
int exp7 = weight1[bonus3 / 10] * 80; int exp4 = (10 - armourClass) * 40;
int exp11 = bonus2 > 0 ? exp2 + 20 : 0; int exp5 = getBonus (35, mageSpellLevel);
int exp12 = getBonus (35, Integer.bitCount (resistance & 0x7E)); int exp6 = getBonus (35, priestSpellLevel);
int exp9 = getBonus (40, Integer.bitCount (abilities & 0x7F)); int exp10 = getBonus (200, levelDrain);
int exp8 = getBonus (90, bonus1);
text.append ("ID .............. " + monsterID); int exp7 = weight1[bonus3 / 10] * 80;
text.append ("\nMonster name .... " + realName); int exp11 = bonus2 > 0 ? exp2 + 20 : 0;
text.append ("\nGeneric name .... " + genericName); int exp12 = getBonus (35, Integer.bitCount (resistance & 0x7E));
int exp9 = getBonus (40, Integer.bitCount (abilities & 0x7F));
text.append ("\n\nImage ID ........ " + imageID);
text.append ("\nGroup size ...... " + groupSize); text.append ("ID .............. " + monsterID);
text.append ("\nHit points ...... " + hitPoints); text.append ("\nMonster name .... " + realName);
if (debug) text.append ("\nGeneric name .... " + genericName);
text.append (" " + exp2);
text.append ("\n\nImage ID ........ " + imageID);
text.append ("\n\nMonster class ... " + type + " " + monsterClass[type]); text.append ("\nGroup size ...... " + groupSize);
text.append ("\nArmour class .... " + armourClass); text.append ("\nHit points ...... " + hitPoints);
if (debug) if (debug)
text.append (" " + exp4); text.append (" " + exp2);
text.append ("\nSpeed ........... " + speed);
if (debug) text.append ("\n\nMonster class ... " + type + " " + monsterClass[type]);
text.append (" " + exp3); text.append ("\nArmour class .... " + armourClass);
if (debug)
text.append ("\n\nDamage .......... " + getDamage ()); text.append (" " + exp4);
text.append ("\nSpeed ........... " + speed);
text.append ("\n\nLevel drain ..... " + levelDrain); if (debug)
if (debug) text.append (" " + exp3);
text.append (" " + exp10);
text.append ("\nExtra hit pts? .. " + bonus1); text.append ("\n\nDamage .......... " + getDamage ());
if (debug)
text.append (" " + exp8); text.append ("\n\nLevel drain ..... " + levelDrain);
if (debug)
text.append ("\n\nPartner ID ...... " + partnerID); text.append (" " + exp10);
if (partnerOdds > 0) text.append ("\nExtra hit pts? .. " + bonus1);
text.append (" " + monsters.get (partnerID).name); if (debug)
text.append ("\nPartner odds .... " + partnerOdds + "%"); text.append (" " + exp8);
text.append ("\n\nMage level ...... " + mageSpellLevel); text.append ("\n\nPartner ID ...... " + partnerID);
if (debug) if (partnerOdds > 0)
text.append (" " + exp5); text.append (" " + monsters.get (partnerID).name);
text.append ("\nPriest level .... " + priestSpellLevel); text.append ("\nPartner odds .... " + partnerOdds + "%");
if (debug)
text.append (" " + exp6); text.append ("\n\nMage level ...... " + mageSpellLevel);
if (debug)
text.append ("\n\nExperience bonus " + bonus2); text.append (" " + exp5);
if (debug) text.append ("\nPriest level .... " + priestSpellLevel);
text.append (" " + exp11); if (debug)
text.append ("\nExperience bonus " + bonus3); text.append (" " + exp6);
if (debug)
text.append (" " + exp7); text.append ("\n\nExperience bonus " + bonus2);
if (debug)
text.append ("\n\nResistance ...... " + String.format ("%02X", resistance)); text.append (" " + exp11);
if (debug) text.append ("\nExperience bonus " + bonus3);
text.append (" " + exp12); if (debug)
text.append ("\nAbilities ....... " + String.format ("%02X", abilities)); text.append (" " + exp7);
if (debug)
text.append (" " + exp9); text.append ("\n\nResistance ...... " + String.format ("%02X", resistance));
if (debug)
text.append ("\n\nExperience ...... " + (exp2 + exp3 + exp4 + exp5 + exp6 + exp7 text.append (" " + exp12);
+ exp8 + exp9 + exp10 + exp11 + exp12)); text.append ("\nAbilities ....... " + String.format ("%02X", abilities));
if (debug)
text.append ("\n\n===== Gold reward ======"); text.append (" " + exp9);
// text.append ("\nTable ........... " + rewardTable1);
text.append ("\n" + goldReward.getText (false)); text.append ("\n\nExperience ...... " + (exp2 + exp3 + exp4 + exp5 + exp6 + exp7
text.append ("===== Chest reward ====="); + exp8 + exp9 + exp10 + exp11 + exp12));
// text.append ("\nTable ........... " + rewardTable2);
text.append ("\n" + chestReward.getText (false)); text.append ("\n\n===== Gold reward ======");
// text.append ("\nTable ........... " + rewardTable1);
while (text.charAt (text.length () - 1) == 10) text.append ("\n" + goldReward.getText (false));
text.deleteCharAt (text.length () - 1); text.append ("===== Chest reward =====");
// text.append ("\nTable ........... " + rewardTable2);
return text.toString (); text.append ("\n" + chestReward.getText (false));
}
while (text.charAt (text.length () - 1) == 10)
public int getExperience () text.deleteCharAt (text.length () - 1);
{
// these values definitely affect the damage a monster does (when breathing?) return text.toString ();
int exp2 = ((buffer[72] & 0xFF) * (buffer[74] & 0xFF) - 1) * 20; }
int exp3 = weight2[speed];
int exp4 = (10 - armourClass) * 40; // ---------------------------------------------------------------------------------//
int exp5 = getBonus (35, mageSpellLevel); public int getExperience ()
int exp6 = getBonus (35, priestSpellLevel); // ---------------------------------------------------------------------------------//
int exp10 = getBonus (200, levelDrain); {
int exp8 = getBonus (90, bonus1); // these values definitely affect the damage a monster does (when breathing?)
int exp7 = weight1[bonus3 / 10] * 80; int exp2 = ((buffer[72] & 0xFF) * (buffer[74] & 0xFF) - 1) * 20;
int exp11 = bonus2 > 0 ? exp2 + 20 : 0; int exp3 = weight2[speed];
int exp12 = getBonus (35, Integer.bitCount (resistance & 0x7E)); int exp4 = (10 - armourClass) * 40;
int exp9 = getBonus (40, Integer.bitCount (abilities & 0x7F)); int exp5 = getBonus (35, mageSpellLevel);
return exp2 + exp3 + exp4 + exp5 + exp6 + exp7 + exp8 + exp9 + exp10 + exp11 + exp12; int exp6 = getBonus (35, priestSpellLevel);
} int exp10 = getBonus (200, levelDrain);
int exp8 = getBonus (90, bonus1);
private int getBonus (int base, int value) int exp7 = weight1[bonus3 / 10] * 80;
{ int exp11 = bonus2 > 0 ? exp2 + 20 : 0;
return base * pwr[value]; int exp12 = getBonus (35, Integer.bitCount (resistance & 0x7E));
} int exp9 = getBonus (40, Integer.bitCount (abilities & 0x7F));
return exp2 + exp3 + exp4 + exp5 + exp6 + exp7 + exp8 + exp9 + exp10 + exp11 + exp12;
public void setImage (BufferedImage image) }
{
this.image = image; // ---------------------------------------------------------------------------------//
} private int getBonus (int base, int value)
// ---------------------------------------------------------------------------------//
@Override {
public String getName () return base * pwr[value];
{ }
return realName;
} // ---------------------------------------------------------------------------------//
public void setImage (BufferedImage image)
public String getRealName () // ---------------------------------------------------------------------------------//
{ {
return realName; this.image = image;
} }
public String getDamage () // ---------------------------------------------------------------------------------//
{ @Override
StringBuilder text = new StringBuilder (); public String getName ()
for (Dice d : damage) // ---------------------------------------------------------------------------------//
text.append (d + ", "); {
text.deleteCharAt (text.length () - 1); return realName;
text.deleteCharAt (text.length () - 1); }
return text.toString ();
} // ---------------------------------------------------------------------------------//
public String getRealName ()
public String getDump (int block) // ---------------------------------------------------------------------------------//
{ {
StringBuilder line = return realName;
new StringBuilder (String.format ("%3d %-16s", monsterID, realName)); }
int lo = block == 0 ? 64 : block == 1 ? 88 : block == 2 ? 112 : 136;
int hi = lo + 24; // ---------------------------------------------------------------------------------//
if (hi > buffer.length) public String getDamage ()
hi = buffer.length; // ---------------------------------------------------------------------------------//
for (int i = lo; i < hi; i++) {
line.append (String.format ("%02X ", buffer[i])); StringBuilder text = new StringBuilder ();
if (block == 3) for (Dice d : damage)
{ text.append (d + ", ");
int exp = getExperience (); text.deleteCharAt (text.length () - 1);
line.append (String.format (" %,6d", exp)); text.deleteCharAt (text.length () - 1);
if (exp != experience[monsterID]) return text.toString ();
line.append (String.format (" %,6d", experience[monsterID])); }
}
return line.toString (); // ---------------------------------------------------------------------------------//
} public String getDump (int block)
// ---------------------------------------------------------------------------------//
public boolean match (int monsterID) {
{ StringBuilder line =
return this.monsterID == monsterID; new StringBuilder (String.format ("%3d %-16s", monsterID, realName));
} int lo = block == 0 ? 64 : block == 1 ? 88 : block == 2 ? 112 : 136;
int hi = lo + 24;
@Override if (hi > buffer.length)
public int compareTo (Monster other) // where is this used? hi = buffer.length;
{ for (int i = lo; i < hi; i++)
if (this.type == other.type) line.append (String.format ("%02X ", buffer[i]));
return 0; if (block == 3)
if (this.type < other.type) {
return -1; int exp = getExperience ();
return 1; line.append (String.format (" %,6d", exp));
} if (exp != experience[monsterID])
line.append (String.format (" %,6d", experience[monsterID]));
@Override }
public String toString () return line.toString ();
{ }
return realName;
} // ---------------------------------------------------------------------------------//
public boolean match (int monsterID)
// ---------------------------------------------------------------------------------//
{
return this.monsterID == monsterID;
}
// ---------------------------------------------------------------------------------//
@Override
public int compareTo (Monster other) // where is this used?
// ---------------------------------------------------------------------------------//
{
if (this.type == other.type)
return 0;
if (this.type < other.type)
return -1;
return 1;
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
return realName;
}
} }

View File

@ -1,18 +1,24 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
class PlainMessage extends Message // -----------------------------------------------------------------------------------//
{ class PlainMessage extends Message
public PlainMessage (byte[] buffer) // -----------------------------------------------------------------------------------//
{ {
super (buffer); // ---------------------------------------------------------------------------------//
} PlainMessage (byte[] buffer)
// ---------------------------------------------------------------------------------//
@Override {
protected String getLine (int offset) super (buffer);
{ }
int length = buffer[offset] & 0xFF;
return HexFormatter.getString (buffer, offset + 1, length); // ---------------------------------------------------------------------------------//
} @Override
protected String getLine (int offset)
// ---------------------------------------------------------------------------------//
{
int length = buffer[offset] & 0xFF;
return HexFormatter.getString (buffer, offset + 1, length);
}
} }

View File

@ -9,7 +9,9 @@ import com.bytezone.diskbrowser.disk.Disk;
import com.bytezone.diskbrowser.disk.DiskAddress; import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
// -----------------------------------------------------------------------------------//
public class Relocator extends AbstractFile public class Relocator extends AbstractFile
// -----------------------------------------------------------------------------------//
{ {
private final int checkByte; private final int checkByte;
private final List<DiskRecord> diskRecords = new ArrayList<> (); private final List<DiskRecord> diskRecords = new ArrayList<> ();
@ -17,7 +19,9 @@ public class Relocator extends AbstractFile
private final int[] diskBlocks = new int[0x800]; private final int[] diskBlocks = new int[0x800];
private final int[] diskOffsets = new int[0x800]; private final int[] diskOffsets = new int[0x800];
// ---------------------------------------------------------------------------------//
public Relocator (String name, byte[] buffer) public Relocator (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{ {
super (name, buffer); super (name, buffer);
@ -37,7 +41,9 @@ public class Relocator extends AbstractFile
addLogicalBlock ((byte) diskRecord.diskNumber, diskSegment); addLogicalBlock ((byte) diskRecord.diskNumber, diskSegment);
} }
// ---------------------------------------------------------------------------------//
private void addLogicalBlock (byte disk, DiskSegment diskSegment) private void addLogicalBlock (byte disk, DiskSegment diskSegment)
// ---------------------------------------------------------------------------------//
{ {
int lo = diskSegment.logicalBlock; int lo = diskSegment.logicalBlock;
int hi = diskSegment.logicalBlock + diskSegment.segmentLength; int hi = diskSegment.logicalBlock + diskSegment.segmentLength;
@ -50,7 +56,9 @@ public class Relocator extends AbstractFile
} }
} }
// ---------------------------------------------------------------------------------//
public void createNewBuffer (Disk[] dataDisks) public void createNewBuffer (Disk[] dataDisks)
// ---------------------------------------------------------------------------------//
{ {
AppleDisk master = (AppleDisk) dataDisks[0]; AppleDisk master = (AppleDisk) dataDisks[0];
// byte[] key1 = { 0x55, 0x55, 0x15, 0x55 }; // byte[] key1 = { 0x55, 0x55, 0x15, 0x55 };
@ -78,8 +86,10 @@ public class Relocator extends AbstractFile
} }
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public String getText () public String getText ()
// ---------------------------------------------------------------------------------//
{ {
StringBuilder text = new StringBuilder (); StringBuilder text = new StringBuilder ();
@ -149,7 +159,9 @@ public class Relocator extends AbstractFile
return text.toString (); return text.toString ();
} }
// ---------------------------------------------------------------------------------//
private class DiskRecord private class DiskRecord
// ---------------------------------------------------------------------------------//
{ {
int diskNumber; int diskNumber;
int totDiskSegments; int totDiskSegments;
@ -202,7 +214,9 @@ public class Relocator extends AbstractFile
} }
} }
// ---------------------------------------------------------------------------------//
private class DiskSegment private class DiskSegment
// ---------------------------------------------------------------------------------//
{ {
int logicalBlock; int logicalBlock;
int physicalBlock; int physicalBlock;

View File

@ -1,141 +1,155 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
class Reward extends AbstractFile // -----------------------------------------------------------------------------------//
{ class Reward extends AbstractFile
static String[] types = { "gold", "item" }; // -----------------------------------------------------------------------------------//
static final int SEGMENT_LENGTH = 18; {
int id; static String[] types = { "gold", "item" };
int totalElements; static final int SEGMENT_LENGTH = 18;
List<RewardElement> elements; int id;
List<Item> items; int totalElements;
List<Monster> goldMonsters = new ArrayList<> (); List<RewardElement> elements;
List<Monster> chestMonsters = new ArrayList<> (); List<Item> items;
List<Monster> goldMonsters = new ArrayList<> ();
public Reward (String name, byte[] buffer, int id, List<Item> items) List<Monster> chestMonsters = new ArrayList<> ();
{
super (name, buffer); // ---------------------------------------------------------------------------------//
this.id = id; Reward (String name, byte[] buffer, int id, List<Item> items)
this.items = items; // ---------------------------------------------------------------------------------//
totalElements = buffer[4]; {
elements = new ArrayList<> (totalElements); super (name, buffer);
this.id = id;
for (int i = 0; i < totalElements; i++) this.items = items;
{ totalElements = buffer[4];
byte[] buffer2 = new byte[SEGMENT_LENGTH]; elements = new ArrayList<> (totalElements);
System.arraycopy (buffer, i * SEGMENT_LENGTH, buffer2, 0, SEGMENT_LENGTH);
elements.add (new RewardElement (buffer2)); for (int i = 0; i < totalElements; i++)
} {
} byte[] buffer2 = new byte[SEGMENT_LENGTH];
System.arraycopy (buffer, i * SEGMENT_LENGTH, buffer2, 0, SEGMENT_LENGTH);
public void addMonster (Monster monster, int location) elements.add (new RewardElement (buffer2));
{ }
if (location == 0) }
goldMonsters.add (monster);
else // ---------------------------------------------------------------------------------//
chestMonsters.add (monster); public void addMonster (Monster monster, int location)
} // ---------------------------------------------------------------------------------//
{
@Override if (location == 0)
public String getText () goldMonsters.add (monster);
{ else
return getText (true); chestMonsters.add (monster);
} }
public String getText (boolean showLinks) // ---------------------------------------------------------------------------------//
{ @Override
StringBuilder text = new StringBuilder (); public String getText ()
for (RewardElement re : elements) // ---------------------------------------------------------------------------------//
text.append (re.getDetail () + "\n"); {
return getText (true);
if (showLinks) }
{
if (goldMonsters.size () > 0) // ---------------------------------------------------------------------------------//
{ public String getText (boolean showLinks)
text.append ("Without chest:\n\n"); // ---------------------------------------------------------------------------------//
for (Monster m : goldMonsters) {
text.append (" " + m + "\n"); StringBuilder text = new StringBuilder ();
text.append ("\n"); for (RewardElement re : elements)
} text.append (re.getDetail () + "\n");
if (chestMonsters.size () > 0)
{ if (showLinks)
text.append ("With chest:\n\n"); {
for (Monster m : chestMonsters) if (goldMonsters.size () > 0)
text.append (" " + m + "\n"); {
} text.append ("Without chest:\n\n");
} for (Monster m : goldMonsters)
return text.toString (); text.append (" " + m + "\n");
} text.append ("\n");
}
public String getDump () if (chestMonsters.size () > 0)
{ {
StringBuilder text = new StringBuilder (); text.append ("With chest:\n\n");
int seq = 0; for (Monster m : chestMonsters)
for (RewardElement re : elements) text.append (" " + m + "\n");
{ }
text.append (seq++ == 0 ? String.format ("%02X : ", id) : " "); }
text.append (re + "\n"); return text.toString ();
} }
return text.toString (); // ---------------------------------------------------------------------------------//
} public String getDump ()
// ---------------------------------------------------------------------------------//
private class RewardElement {
{ StringBuilder text = new StringBuilder ();
int type; int seq = 0;
int odds; for (RewardElement re : elements)
byte[] buffer; {
text.append (seq++ == 0 ? String.format ("%02X : ", id) : " ");
public RewardElement (byte[] buffer) text.append (re + "\n");
{ }
this.buffer = buffer;
type = buffer[8]; return text.toString ();
odds = buffer[6]; }
}
// ---------------------------------------------------------------------------------//
@Override private class RewardElement
public String toString () // ---------------------------------------------------------------------------------//
{ {
StringBuilder text = new StringBuilder (); int type;
for (int i = 0; i < SEGMENT_LENGTH; i += 2) int odds;
text.append (String.format ("%3d ", buffer[i] & 0xFF)); byte[] buffer;
return text.toString ();
} public RewardElement (byte[] buffer)
{
public String getDetail () this.buffer = buffer;
{ type = buffer[8];
StringBuilder text = new StringBuilder (); odds = buffer[6];
text.append ("Odds ............ " + odds + "%\n"); }
switch (type) @Override
{ public String toString ()
case 0: {
text.append ("Gold ............ " + buffer[10] + "d" + buffer[12] + "\n"); StringBuilder text = new StringBuilder ();
break; for (int i = 0; i < SEGMENT_LENGTH; i += 2)
case 1: text.append (String.format ("%3d ", buffer[i] & 0xFF));
int lo = buffer[10] & 0xFF; return text.toString ();
int qty = buffer[16] & 0xFF; }
boolean title = true;
String[] lineItem = new String[4]; public String getDetail ()
for (int i = lo, max = lo + qty; i <= max; i += lineItem.length) {
{ StringBuilder text = new StringBuilder ();
String lineTitle = title ? "Items ..........." : ""; text.append ("Odds ............ " + odds + "%\n");
title = false;
for (int j = 0; j < lineItem.length; j++) switch (type)
lineItem[j] = i + j <= max ? items.get (i + j).getName () : ""; {
text.append (String.format ("%-17s %-16s %-16s %-16s %-16s%n", lineTitle, case 0:
lineItem[0], lineItem[1], lineItem[2], lineItem[3])); text.append ("Gold ............ " + buffer[10] + "d" + buffer[12] + "\n");
} break;
break; case 1:
default: int lo = buffer[10] & 0xFF;
System.out.println ("Unknown reward type " + type); int qty = buffer[16] & 0xFF;
} boolean title = true;
String[] lineItem = new String[4];
return text.toString (); for (int i = lo, max = lo + qty; i <= max; i += lineItem.length)
} {
} String lineTitle = title ? "Items ..........." : "";
title = false;
for (int j = 0; j < lineItem.length; j++)
lineItem[j] = i + j <= max ? items.get (i + j).getName () : "";
text.append (String.format ("%-17s %-16s %-16s %-16s %-16s%n", lineTitle,
lineItem[0], lineItem[1], lineItem[2], lineItem[3]));
}
break;
default:
System.out.println ("Unknown reward type " + type);
}
return text.toString ();
}
}
} }

View File

@ -1,369 +1,408 @@
package com.bytezone.diskbrowser.wizardry; package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
class Spell extends AbstractFile // -----------------------------------------------------------------------------------//
{ class Spell extends AbstractFile
private final SpellType spellType; // -----------------------------------------------------------------------------------//
private SpellThrown whenCast; {
private final int level; private final SpellType spellType;
private String translation; private SpellThrown whenCast;
private SpellTarget target; private final int level;
private String description; private String translation;
private SpellTarget target;
public enum SpellType { private String description;
MAGE, PRIEST
}; public enum SpellType
{
public enum SpellTarget { MAGE, PRIEST
PERSON, PARTY, MONSTER, MONSTER_GROUP, ALL_MONSTERS, VARIABLE, NONE, CASTER };
};
public enum SpellTarget
public enum SpellThrown { {
COMBAT, ANY_TIME, LOOTING, CAMP, COMBAT_OR_CAMP PERSON, PARTY, MONSTER, MONSTER_GROUP, ALL_MONSTERS, VARIABLE, NONE, CASTER
}; };
private static int lastSpellFound = -1; public enum SpellThrown
{
private Spell (String spellName, SpellType type, int level, byte[] buffer) COMBAT, ANY_TIME, LOOTING, CAMP, COMBAT_OR_CAMP
{ };
super (spellName, buffer);
this.spellType = type; private static int lastSpellFound = -1;
this.level = level;
// ---------------------------------------------------------------------------------//
if (lastSpellFound + 1 < spellNames.length && spellName.equals (spellNames[lastSpellFound + 1])) private Spell (String spellName, SpellType type, int level, byte[] buffer)
setSpell (++lastSpellFound); // ---------------------------------------------------------------------------------//
else {
{ super (spellName, buffer);
for (int i = 0; i < spellNames.length; i++) this.spellType = type;
if (spellName.equals (spellNames[i])) this.level = level;
{
setSpell (i); if (lastSpellFound + 1 < spellNames.length
lastSpellFound = i; && spellName.equals (spellNames[lastSpellFound + 1]))
break; setSpell (++lastSpellFound);
} else
} {
} for (int i = 0; i < spellNames.length; i++)
if (spellName.equals (spellNames[i]))
private void setSpell (int spellNo) {
{ setSpell (i);
this.translation = translations[spellNo]; lastSpellFound = i;
this.description = descriptions[spellNo]; break;
this.whenCast = when[spellNo]; }
this.target = affects[spellNo]; }
} }
public static Spell getSpell (String spellName, SpellType type, int level, byte[] buffer) // ---------------------------------------------------------------------------------//
{ private void setSpell (int spellNo)
return new Spell (spellName, type, level, buffer); // ---------------------------------------------------------------------------------//
} {
this.translation = translations[spellNo];
public String getName () this.description = descriptions[spellNo];
{ this.whenCast = when[spellNo];
return name; this.target = affects[spellNo];
} }
public SpellType getType () // ---------------------------------------------------------------------------------//
{ public static Spell getSpell (String spellName, SpellType type, int level,
return spellType; byte[] buffer)
} // ---------------------------------------------------------------------------------//
{
public int getLevel () return new Spell (spellName, type, level, buffer);
{ }
return level;
} // ---------------------------------------------------------------------------------//
@Override
public String getTranslation () public String getName ()
{ // ---------------------------------------------------------------------------------//
return translation; {
} return name;
}
@Override
public String getText () // ---------------------------------------------------------------------------------//
{ public SpellType getType ()
return description; // ---------------------------------------------------------------------------------//
} {
return spellType;
public String getWhenCast () }
{
switch (whenCast) // ---------------------------------------------------------------------------------//
{ public int getLevel ()
case COMBAT: // ---------------------------------------------------------------------------------//
return "Combat"; {
case LOOTING: return level;
return "Looting"; }
case ANY_TIME:
return "Any time"; // ---------------------------------------------------------------------------------//
case CAMP: public String getTranslation ()
return "Camp"; // ---------------------------------------------------------------------------------//
case COMBAT_OR_CAMP: {
return "Combat or camp"; return translation;
default: }
return "?";
} // ---------------------------------------------------------------------------------//
@Override
} public String getText ()
// ---------------------------------------------------------------------------------//
public String getArea () {
{ return description;
switch (target) }
{
case PERSON: // ---------------------------------------------------------------------------------//
return "1 Person"; public String getWhenCast ()
case PARTY: // ---------------------------------------------------------------------------------//
return "Entire party"; {
case MONSTER: switch (whenCast)
return "1 Monster"; {
case MONSTER_GROUP: case COMBAT:
return "1 Monster group"; return "Combat";
case ALL_MONSTERS: case LOOTING:
return "All monsters"; return "Looting";
case VARIABLE: case ANY_TIME:
return "Variable"; return "Any time";
case NONE: case CAMP:
return "None"; return "Camp";
case CASTER: case COMBAT_OR_CAMP:
return "Caster"; return "Combat or camp";
default: default:
return "?"; return "?";
} }
} }
public String toHTMLTable () // ---------------------------------------------------------------------------------//
{ public String getArea ()
StringBuilder text = new StringBuilder ("<table border=\"1\""); // ---------------------------------------------------------------------------------//
text.append (" width=\"100%\">\n"); {
switch (target)
text.append (" <tr>\n <td width=\"110\">Spell name</td>\n"); {
text.append (" <td>" + name + "</td>\n </tr>\n"); case PERSON:
return "1 Person";
text.append (" <tr>\n <td>Translation</td>\n"); case PARTY:
text.append (" <td>" + translation + "</td>\n </tr>\n"); return "Entire party";
case MONSTER:
text.append (" <tr>\n <td>Spell level</td>\n"); return "1 Monster";
text.append (" <td>" + level + "</td>\n </tr>\n"); case MONSTER_GROUP:
return "1 Monster group";
text.append (" <tr>\n <td>Spell type</td>\n"); case ALL_MONSTERS:
text.append (" <td>" + getWhenCast () + "</td>\n </tr>\n"); return "All monsters";
case VARIABLE:
text.append (" <tr>\n <td>Area of effect</td>\n"); return "Variable";
text.append (" <td>" + getArea () + "</td>\n </tr>\n"); case NONE:
return "None";
text.append (" <tr>\n <td>Description</td>\n"); case CASTER:
text.append (" <td>" + getText () + "</td>\n </tr>\n"); return "Caster";
default:
text.append ("</table>"); return "?";
return text.toString (); }
} }
@Override // ---------------------------------------------------------------------------------//
public String toString () public String toHTMLTable ()
{ // ---------------------------------------------------------------------------------//
StringBuilder text = new StringBuilder (name); {
while (text.length () < 14) StringBuilder text = new StringBuilder ("<table border=\"1\"");
text.append (" "); text.append (" width=\"100%\">\n");
if (spellType == SpellType.PRIEST)
text.append ("P"); text.append (" <tr>\n <td width=\"110\">Spell name</td>\n");
else text.append (" <td>" + name + "</td>\n </tr>\n");
text.append ("M");
text.append (level); text.append (" <tr>\n <td>Translation</td>\n");
while (text.length () < 20) text.append (" <td>" + translation + "</td>\n </tr>\n");
text.append (" ");
text.append (translation); text.append (" <tr>\n <td>Spell level</td>\n");
while (text.length () < 40) text.append (" <td>" + level + "</td>\n </tr>\n");
text.append (" ");
text.append (getArea ()); text.append (" <tr>\n <td>Spell type</td>\n");
while (text.length () < 60) text.append (" <td>" + getWhenCast () + "</td>\n </tr>\n");
text.append (" ");
text.append (getWhenCast ()); text.append (" <tr>\n <td>Area of effect</td>\n");
return text.toString (); text.append (" <td>" + getArea () + "</td>\n </tr>\n");
}
text.append (" <tr>\n <td>Description</td>\n");
private static String[] spellNames = text.append (" <td>" + getText () + "</td>\n </tr>\n");
{ "KALKI", "DIOS", "BADIOS", "MILWA", "PORFIC", "MATU", "CALFO", "MANIFO", "MONTINO",
"LOMILWA", "DIALKO", "LATUMAPIC", "BAMATU", "DIAL", "BADIAL", "LATUMOFIS", "MAPORFIC", text.append ("</table>");
"DIALMA", "BADIALMA", "LITOKAN", "KANDI", "DI", "BADI", "LORTO", "MADI", "MABADI", return text.toString ();
"LOKTOFEIT", "MALIKTO", "KADORTO", }
"HALITO", "MOGREF", "KATINO", "DUMAPIC", "DILTO", "SOPIC", "MAHALITO", "MOLITO", // ---------------------------------------------------------------------------------//
"MORLIS", "DALTO", "LAHALITO", "MAMORLIS", "MAKANITO", "MADALTO", "LAKANITO", "ZILWAN", @Override
"MASOPIC", "HAMAN", "MALOR", "MAHAMAN", "TILTOWAIT" }; public String toString ()
// ---------------------------------------------------------------------------------//
private static String[] translations = {
{ "Blessings", "Heal", "Harm", "Light", "Shield", "Blessing & zeal", "X-ray vision", StringBuilder text = new StringBuilder (name);
"Statue", "Still air", "More light", "Softness/supple", "Identification", "Prayer", while (text.length () < 14)
"Heal (more)", "Hurt (more)", "Cure poison", "Shield (big)", "Heal (greatly)", text.append (" ");
"Hurt (greatly)", "Flame tower", "Location", "Life", "Death", "Blades", "Healing", if (spellType == SpellType.PRIEST)
"Harm (incredibly)", "Recall", "The Word of Death", "Resurrection", text.append ("P");
else
"Little Fire", "Body Iron", "Bad Air", "Clarity", "Darkness", "Glass", "Big fire", text.append ("M");
"Spark storm", "Fear", "Blizzard blast", "Flame storm", "Terror", "Deadly air", "Frost", text.append (level);
"Suffocation", "Dispell", "Big glass", "Change", "Apport", "Great change", while (text.length () < 20)
"(untranslatable)" }; text.append (" ");
text.append (translation);
private static SpellThrown[] when = while (text.length () < 40)
{ SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.ANY_TIME, text.append (" ");
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.LOOTING, SpellThrown.COMBAT, text.append (getArea ());
SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.ANY_TIME, SpellThrown.COMBAT, while (text.length () < 60)
SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.ANY_TIME, text.append (" ");
SpellThrown.ANY_TIME, SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT, text.append (getWhenCast ());
SpellThrown.CAMP, SpellThrown.CAMP, SpellThrown.COMBAT, SpellThrown.COMBAT, return text.toString ();
SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, }
SpellThrown.ANY_TIME,
private static String[] spellNames =
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.CAMP, { "KALKI", "DIOS", "BADIOS", "MILWA", "PORFIC", "MATU", "CALFO", "MANIFO",
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, "MONTINO", "LOMILWA", "DIALKO", "LATUMAPIC", "BAMATU", "DIAL", "BADIAL",
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, "LATUMOFIS", "MAPORFIC", "DIALMA", "BADIALMA", "LITOKAN", "KANDI", "DI", "BADI",
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, "LORTO", "MADI", "MABADI", "LOKTOFEIT", "MALIKTO", "KADORTO",
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT_OR_CAMP, SpellThrown.COMBAT,
SpellThrown.COMBAT, }; "HALITO", "MOGREF", "KATINO", "DUMAPIC", "DILTO", "SOPIC", "MAHALITO", "MOLITO",
"MORLIS", "DALTO", "LAHALITO", "MAMORLIS", "MAKANITO", "MADALTO", "LAKANITO",
private static SpellTarget[] affects = "ZILWAN", "MASOPIC", "HAMAN", "MALOR", "MAHAMAN", "TILTOWAIT" };
{ SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PARTY,
SpellTarget.CASTER, SpellTarget.PARTY, SpellTarget.CASTER, SpellTarget.MONSTER_GROUP, private static String[] translations =
SpellTarget.MONSTER_GROUP, SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.PARTY, { "Blessings", "Heal", "Harm", "Light", "Shield", "Blessing & zeal", "X-ray vision",
SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PERSON, "Statue", "Still air", "More light", "Softness/supple", "Identification",
SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PARTY, "Prayer", "Heal (more)", "Hurt (more)", "Cure poison", "Shield (big)",
SpellTarget.PERSON, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.MONSTER_GROUP, "Heal (greatly)", "Hurt (greatly)", "Flame tower", "Location", "Life", "Death",
SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PARTY, SpellTarget.MONSTER_GROUP, "Blades", "Healing", "Harm (incredibly)", "Recall", "The Word of Death",
SpellTarget.PERSON, "Resurrection",
SpellTarget.MONSTER, SpellTarget.CASTER, SpellTarget.MONSTER_GROUP, SpellTarget.NONE, "Little Fire", "Body Iron", "Bad Air", "Clarity", "Darkness", "Glass", "Big fire",
SpellTarget.MONSTER_GROUP, SpellTarget.CASTER, SpellTarget.MONSTER_GROUP, "Spark storm", "Fear", "Blizzard blast", "Flame storm", "Terror", "Deadly air",
SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, "Frost", "Suffocation", "Dispell", "Big glass", "Change", "Apport",
SpellTarget.MONSTER_GROUP, SpellTarget.ALL_MONSTERS, SpellTarget.ALL_MONSTERS, "Great change", "(untranslatable)" };
SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER,
SpellTarget.PARTY, SpellTarget.VARIABLE, SpellTarget.PARTY, SpellTarget.PARTY, private static SpellThrown[] when =
SpellTarget.ALL_MONSTERS }; { SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.COMBAT,
SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.LOOTING,
private static String[] descriptions = SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.ANY_TIME,
{ SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT,
"KALKI reduces the AC of all party members by one, and thus makes" SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.ANY_TIME,
+ " them harder to hit.", SpellThrown.ANY_TIME, SpellThrown.ANY_TIME, SpellThrown.COMBAT,
"DIOS restores from one to eight hit points of damage from a party" SpellThrown.COMBAT, SpellThrown.CAMP, SpellThrown.CAMP, SpellThrown.COMBAT,
+ "member. It will not bring dead back to life.", SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT,
"BADIOS causes one to eight hit points of damage to a monster, and" SpellThrown.COMBAT, SpellThrown.ANY_TIME,
+ " may kill it. It is the reverse of dios. Note the BA prefix which"
+ " means 'not'.", SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.CAMP,
"MILWA causes a softly glowing light to follow the party, allowing" SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
+ " them to see further into the maze, and also revealing all secret" SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
+ " doors. See also LOMILWA. This spell lasts only a short while.", SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
"PORFIC lowers the AC of the caster considerably. The effects last" SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT_OR_CAMP,
+ " for the duration of combat.", SpellThrown.COMBAT, SpellThrown.COMBAT, };
"MATU has the same effects as KALKI, but at double the strength.",
"CALFO allows the caster to determine the exact nature of a trap" private static SpellTarget[] affects =
+ " on a chest 95% of the time.", { SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PARTY,
"MANIFO causes some of the monsters in a group to become stiff as" SpellTarget.CASTER, SpellTarget.PARTY, SpellTarget.CASTER,
+ " statues for one or more melee rounds. The chance of success," SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.PARTY,
+ " and the duration of the effects, depend on the power of the" SpellTarget.PERSON, SpellTarget.PARTY, SpellTarget.PARTY, SpellTarget.PERSON,
+ " target monsters.", SpellTarget.MONSTER, SpellTarget.PERSON, SpellTarget.PARTY, SpellTarget.PERSON,
"MONTINO causes the air around a group of monsters to stop" SpellTarget.MONSTER, SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.PERSON,
+ " transmitting sound. Like MANIFO, only some of the monsters will" SpellTarget.MONSTER, SpellTarget.MONSTER_GROUP, SpellTarget.PERSON,
+ " be affected, and for varying lengths of time. Monsters and" SpellTarget.MONSTER, SpellTarget.PARTY, SpellTarget.MONSTER_GROUP,
+ " Party members under the influence of this spell cannot cast" SpellTarget.PERSON,
+ " spells, as they cannot utter the spell words!",
"LOMILWA is a MILWA spell with a much longer life span. Note that" SpellTarget.MONSTER, SpellTarget.CASTER, SpellTarget.MONSTER_GROUP,
+ " when this spell, or MILWA are active, the Q option while" SpellTarget.NONE, SpellTarget.MONSTER_GROUP, SpellTarget.CASTER,
+ " moving through the maze is active. If Q)UICK PLOTTING is on," SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP,
+ " only the square you are in, and the next two squares, will" SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.ALL_MONSTERS,
+ " plot. Normally you might see five or six squares ahead with" SpellTarget.ALL_MONSTERS, SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP,
+ " LOMILWA on. Quick Plotting lets you move fast through known" SpellTarget.MONSTER, SpellTarget.PARTY, SpellTarget.VARIABLE, SpellTarget.PARTY,
+ " areas. Note that it will be turned off when you enter camp or" SpellTarget.PARTY, SpellTarget.ALL_MONSTERS };
+ " combat mode.",
"DIALKO cures paralysis, and removes the effects of MANIFO and" private static String[] descriptions =
+ " KATINO from one member of the party.", { "KALKI reduces the AC of all party members by one, and thus makes"
"LATUMAPIC makes it readily apparent exactly what the opposing" + " monsters really are.", + " them harder to hit.",
"BAMATU has the effects of MATU at twice the effectiveness.", "DIOS restores from one to eight hit points of damage from a party"
"DIAL restores two to 16 hit points of damage, and is similar to" + " DIOS.", + "member. It will not bring dead back to life.",
"BADIAL causes two to 16 hit points of damage in the same way as" + " BADIOS.", "BADIOS causes one to eight hit points of damage to a monster, and"
"LATUMOFIS makes a poisoned person whole and fit again. Note that" + " may kill it. It is the reverse of dios. Note the BA prefix which"
+ " poison causes a person to lose hit points steadily during" + " means 'not'.",
+ " movement and combat.", "MILWA causes a softly glowing light to follow the party, allowing"
"MAPORFIC is an improved PORFIC, with effects that last for the" + " entire expedition.", + " them to see further into the maze, and also revealing all secret"
"DIALMA restores three to 24 hit points.", + " doors. See also LOMILWA. This spell lasts only a short while.",
"BADIALMA causes three to 24 hit points of damage.", "PORFIC lowers the AC of the caster considerably. The effects last"
"LITOKAN causes a pillar of flame to strike a group of monsters," + " for the duration of combat.",
+ " doing three to 24 hits of damage to each. However, as with" "MATU has the same effects as KALKI, but at double the strength.",
+ " many spells that affect entire groups, there is a chance that" "CALFO allows the caster to determine the exact nature of a trap"
+ " individual monsters will be able to avoid or minimise its" + " on a chest 95% of the time.",
+ " effects. And some monsters will be resistant to it.", "MANIFO causes some of the monsters in a group to become stiff as"
"KANDI allows the user to locate characters in the maze. It tells on" + " statues for one or more melee rounds. The chance of success,"
+ " which level, and in which rough area the dead one can be found.", + " and the duration of the effects, depend on the power of the"
"DI causes a dead person to be resurrected. However, the renewed" + " target monsters.",
+ " character has but one hit point. Also, this spell is not as" "MONTINO causes the air around a group of monsters to stop"
+ " effective or as safe as using the Temple.", + " transmitting sound. Like MANIFO, only some of the monsters will"
"BADI gives the affected monster a coronary attack. It may or may" + " be affected, and for varying lengths of time. Monsters and"
+ " not cause death to occur.", + " Party members under the influence of this spell cannot cast"
"LORTO causes sharp blades to slice through a group, causing six to" + " spells, as they cannot utter the spell words!",
+ " 36 points of damage.", "LOMILWA is a MILWA spell with a much longer life span. Note that"
"MADI causes all hit points to be restored and cures any condition" + " but death.", + " when this spell, or MILWA are active, the Q option while"
"MABADI causes all but one to eight hit points to be removed from" + " the target.", + " moving through the maze is active. If Q)UICK PLOTTING is on,"
"LOKTOFEIT causes all party members to be teleported back to the" + " only the square you are in, and the next two squares, will"
+ " castle, minus all their equipment and most of their gold. There" + " plot. Normally you might see five or six squares ahead with"
+ " is also a good chance this spell will not function.", + " LOMILWA on. Quick Plotting lets you move fast through known"
"MALIKTO causes 12 to 72 hit points of damage to all monsters. None" + " areas. Note that it will be turned off when you enter camp or"
+ " can escape or minimise its effects.", + " combat mode.",
"KADORTO restores the dead to life as does DI, but also restores all" "DIALKO cures paralysis, and removes the effects of MANIFO and"
+ " hit points. However, it has the same drawbacks as the DI spell." + " KATINO from one member of the party.",
+ " KADORTO can be used to resurrect people even if they are ashes.", "LATUMAPIC makes it readily apparent exactly what the opposing"
+ " monsters really are.",
"HALITO causes a flame ball the size of a baseball to hit a monster," "BAMATU has the effects of MATU at twice the effectiveness.",
+ " doing from one to eight points of damage.", "DIAL restores two to 16 hit points of damage, and is similar to" + " DIOS.",
"MOGREF reduces the caster's AC by two. The effect lasts the entire" + " encounter.", "BADIAL causes two to 16 hit points of damage in the same way as" + " BADIOS.",
"KATINO causes most of the monsters in a group to fall asleep." "LATUMOFIS makes a poisoned person whole and fit again. Note that"
+ " Katino only effects normal, animal or humanoid monsters. The" + " poison causes a person to lose hit points steadily during"
+ " chance of the spell affecting an individual monster, and the" + " movement and combat.",
+ " duration of the effect, is inversely proportional to the power" "MAPORFIC is an improved PORFIC, with effects that last for the"
+ " of the monster. While asleep, monsters are easier to hit and" + " entire expedition.",
+ " successful strikes do double damage.", "DIALMA restores three to 24 hit points.",
"DUMAPIC informs you of the party's exact displacement from the" "BADIALMA causes three to 24 hit points of damage.",
+ " stairs to the castle, vertically, and North and East, and also" "LITOKAN causes a pillar of flame to strike a group of monsters,"
+ " tells you what direction you are facing.", + " doing three to 24 hits of damage to each. However, as with"
+ " many spells that affect entire groups, there is a chance that"
"DILTO causes one group of monsters to be enveloped in darkness," + " individual monsters will be able to avoid or minimise its"
+ " which reduces their ability to defend against your attacks.", + " effects. And some monsters will be resistant to it.",
"SOPIC causes the caster to become transparent. This means that" "KANDI allows the user to locate characters in the maze. It tells on"
+ " he is harder to see, and thus his AC is reduced by four.", + " which level, and in which rough area the dead one can be found.",
"DI causes a dead person to be resurrected. However, the renewed"
"MAHALITO causes a fiery explosion in a monster group, doing four" + " character has but one hit point. Also, this spell is not as"
+ " to 24 hit points of damage. As with other similar spells," + " effective or as safe as using the Temple.",
+ " monsters may be able to minimise the damage done.", "BADI gives the affected monster a coronary attack. It may or may"
"MOLITO causes sparks to fly out and damage about half of the" + " not cause death to occur.",
+ " monsters in a group. Three to 18 hit points of damage are done" "LORTO causes sharp blades to slice through a group, causing six to"
+ " with no chance of avoiding the sparks.", + " 36 points of damage.",
"MORLIS causes one group of monsters to fear the party greatly. The" "MADI causes all hit points to be restored and cures any condition"
+ " effects are the same as a double strength DILTO spell.", + " but death.",
"DALTO is similar to MAHALITO except that cold replaces flames." "MABADI causes all but one to eight hit points to be removed from"
+ " Also, six to 36 hit points of damage are done.", + " the target.",
"LAHALITO is an improved MAHALITO, doing the same damage as DALTO.", "LOKTOFEIT causes all party members to be teleported back to the"
"MAMORLIS is similar to MORLIS, except that all monster groups are" + " affected.", + " castle, minus all their equipment and most of their gold. There"
"Any monsters of less than eigth level (i.e. about 35-40 hit points)" + " is also a good chance this spell will not function.",
+ " are killed by this spell outright.", "MALIKTO causes 12 to 72 hit points of damage to all monsters. None"
"An improved DALTO causing eight to 64 hit points of damage.", + " can escape or minimise its effects.",
"All monsters in the group affected by this spell die. Of course," "KADORTO restores the dead to life as does DI, but also restores all"
+ " there is a chance that some of the monsters will not be affected.", + " hit points. However, it has the same drawbacks as the DI spell."
"This spell will destroy any one monster that is of the Undead" + " variety", + " KADORTO can be used to resurrect people even if they are ashes.",
"This spell duplicates the effects of SOPIC for the entire party.",
"This spell is indeed terrible, and may backfire on the caster." "HALITO causes a flame ball the size of a baseball to hit a monster,"
+ " First, to even cast it, you must be of the thirteenth level or" + " doing from one to eight points of damage.",
+ " higher, and casting it will cost you one level of experience." "MOGREF reduces the caster's AC by two. The effect lasts the entire"
+ " The effects of HAMAN are random, and usually help the party.", + " encounter.",
"This spell's effects depend on the situation the party is in when it" "KATINO causes most of the monsters in a group to fall asleep."
+ " is cast.Basically, MALOR will teleport the entire party from one" + " Katino only effects normal, animal or humanoid monsters. The"
+ " location to another. When used in melee, the teleport is random," + " chance of the spell affecting an individual monster, and the"
+ " but when used in camp, where there is more chance for concentration" + " duration of the effect, is inversely proportional to the power"
+ ", it can be used to move the party anywhere in the maze. Be warned," + " of the monster. While asleep, monsters are easier to hit and"
+ " however, that if you teleport outside of the maze, or into an" + " successful strikes do double damage.",
+ " area that is solid rock, you will be lost forever, so this spell" "DUMAPIC informs you of the party's exact displacement from the"
+ " is to be used with the greatest of care. Combat use of MALOR will" + " stairs to the castle, vertically, and North and East, and also"
+ " never put you outside of the maze, but it may move you deeper in," + " tells you what direction you are facing.",
+ " so it should be used only in panic situations.",
"The same restrictions and qualifications apply to this spell as do" "DILTO causes one group of monsters to be enveloped in darkness,"
+ " to HAMAN. However, the effects are even greater. Generally these" + " which reduces their ability to defend against your attacks.",
+ " spells are only used when there is no other hope for survival.", "SOPIC causes the caster to become transparent. This means that"
"The effect of this spell can be described as similar to that of a" + " he is harder to see, and thus his AC is reduced by four.",
+ " nuclear fusion explosion. Luckily the party is shielded from its"
+ " effects. Unluckily (for them) the monsters are not. This spell" "MAHALITO causes a fiery explosion in a monster group, doing four"
+ " will do from 10-100 hit points of damage." }; + " to 24 hit points of damage. As with other similar spells,"
+ " monsters may be able to minimise the damage done.",
"MOLITO causes sparks to fly out and damage about half of the"
+ " monsters in a group. Three to 18 hit points of damage are done"
+ " with no chance of avoiding the sparks.",
"MORLIS causes one group of monsters to fear the party greatly. The"
+ " effects are the same as a double strength DILTO spell.",
"DALTO is similar to MAHALITO except that cold replaces flames."
+ " Also, six to 36 hit points of damage are done.",
"LAHALITO is an improved MAHALITO, doing the same damage as DALTO.",
"MAMORLIS is similar to MORLIS, except that all monster groups are"
+ " affected.",
"Any monsters of less than eigth level (i.e. about 35-40 hit points)"
+ " are killed by this spell outright.",
"An improved DALTO causing eight to 64 hit points of damage.",
"All monsters in the group affected by this spell die. Of course,"
+ " there is a chance that some of the monsters will not be affected.",
"This spell will destroy any one monster that is of the Undead" + " variety",
"This spell duplicates the effects of SOPIC for the entire party.",
"This spell is indeed terrible, and may backfire on the caster."
+ " First, to even cast it, you must be of the thirteenth level or"
+ " higher, and casting it will cost you one level of experience."
+ " The effects of HAMAN are random, and usually help the party.",
"This spell's effects depend on the situation the party is in when it"
+ " is cast.Basically, MALOR will teleport the entire party from one"
+ " location to another. When used in melee, the teleport is random,"
+ " but when used in camp, where there is more chance for concentration"
+ ", it can be used to move the party anywhere in the maze. Be warned,"
+ " however, that if you teleport outside of the maze, or into an"
+ " area that is solid rock, you will be lost forever, so this spell"
+ " is to be used with the greatest of care. Combat use of MALOR will"
+ " never put you outside of the maze, but it may move you deeper in,"
+ " so it should be used only in panic situations.",
"The same restrictions and qualifications apply to this spell as do"
+ " to HAMAN. However, the effects are even greater. Generally these"
+ " spells are only used when there is no other hope for survival.",
"The effect of this spell can be described as similar to that of a"
+ " nuclear fusion explosion. Luckily the party is shielded from its"
+ " effects. Unluckily (for them) the monsters are not. This spell"
+ " will do from 10-100 hit points of damage." };
} }

View File

@ -3,9 +3,13 @@ package com.bytezone.diskbrowser.wizardry;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer; import java.awt.image.DataBuffer;
// -----------------------------------------------------------------------------------//
public class Wiz4Image extends AbstractImage public class Wiz4Image extends AbstractImage
// -----------------------------------------------------------------------------------//
{ {
// ---------------------------------------------------------------------------------//
public Wiz4Image (String name, byte[] buffer, int rows, int cols) // 5, 6 public Wiz4Image (String name, byte[] buffer, int rows, int cols) // 5, 6
// ---------------------------------------------------------------------------------//
{ {
super (name, buffer); super (name, buffer);

View File

@ -6,12 +6,16 @@ import java.util.List;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
// -----------------------------------------------------------------------------------//
public class Wiz4Monsters extends AbstractFile public class Wiz4Monsters extends AbstractFile
// -----------------------------------------------------------------------------------//
{ {
final List<Wiz4Image> images = new ArrayList<> (); final List<Wiz4Image> images = new ArrayList<> ();
final List<Integer> blocks = new ArrayList<> (); final List<Integer> blocks = new ArrayList<> ();
// ---------------------------------------------------------------------------------//
public Wiz4Monsters (String name, byte[] buffer) public Wiz4Monsters (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{ {
super (name, buffer); super (name, buffer);
@ -30,8 +34,10 @@ public class Wiz4Monsters extends AbstractFile
} }
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public String getText () public String getText ()
// ---------------------------------------------------------------------------------//
{ {
StringBuilder text = new StringBuilder (); StringBuilder text = new StringBuilder ();

View File

@ -8,12 +8,16 @@ import com.bytezone.common.Utility;
import com.bytezone.diskbrowser.applefile.AbstractFile; import com.bytezone.diskbrowser.applefile.AbstractFile;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
public class Wiz5Monsters extends AbstractFile implements Iterable<Wiz5Monsters.Monster> // -----------------------------------------------------------------------------------//
class Wiz5Monsters extends AbstractFile implements Iterable<Wiz5Monsters.Monster>
// -----------------------------------------------------------------------------------//
{ {
private static final int BLOCK_SIZE = 512; private static final int BLOCK_SIZE = 512;
private final List<Monster> monsters = new ArrayList<> (); private final List<Monster> monsters = new ArrayList<> ();
public Wiz5Monsters (String name, byte[] buffer) // ---------------------------------------------------------------------------------//
Wiz5Monsters (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{ {
super (name, buffer); super (name, buffer);
@ -56,14 +60,18 @@ public class Wiz5Monsters extends AbstractFile implements Iterable<Wiz5Monsters.
} }
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public Iterator<Monster> iterator () public Iterator<Monster> iterator ()
// ---------------------------------------------------------------------------------//
{ {
return monsters.iterator (); return monsters.iterator ();
} }
// ---------------------------------------------------------------------------------//
@Override @Override
public String getText () public String getText ()
// ---------------------------------------------------------------------------------//
{ {
StringBuilder text = new StringBuilder (); StringBuilder text = new StringBuilder ();
@ -90,7 +98,9 @@ public class Wiz5Monsters extends AbstractFile implements Iterable<Wiz5Monsters.
return text.toString (); return text.toString ();
} }
// ---------------------------------------------------------------------------------//
class Monster class Monster
// ---------------------------------------------------------------------------------//
{ {
private final int id; private final int id;
private final List<DataBuffer> dataBuffers = new ArrayList<> (); private final List<DataBuffer> dataBuffers = new ArrayList<> ();
@ -151,7 +161,9 @@ public class Wiz5Monsters extends AbstractFile implements Iterable<Wiz5Monsters.
} }
} }
// ---------------------------------------------------------------------------------//
class DataBuffer class DataBuffer
// ---------------------------------------------------------------------------------//
{ {
private final int block; private final int block;
private final int offset; private final int offset;

View File

@ -17,7 +17,9 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
import com.bytezone.diskbrowser.utilities.Utility; import com.bytezone.diskbrowser.utilities.Utility;
import com.bytezone.diskbrowser.wizardry.Header.ScenarioData; import com.bytezone.diskbrowser.wizardry.Header.ScenarioData;
// -----------------------------------------------------------------------------------//
public class Wizardry4BootDisk extends PascalDisk public class Wizardry4BootDisk extends PascalDisk
// -----------------------------------------------------------------------------------//
{ {
public Header scenarioHeader; public Header scenarioHeader;
// private final List<AppleDisk> disks = new ArrayList<> (); // private final List<AppleDisk> disks = new ArrayList<> ();
@ -26,7 +28,9 @@ public class Wizardry4BootDisk extends PascalDisk
private Huffman huffman; private Huffman huffman;
private final int version; private final int version;
// ---------------------------------------------------------------------------------//
public Wizardry4BootDisk (AppleDisk[] dataDisks) public Wizardry4BootDisk (AppleDisk[] dataDisks)
// ---------------------------------------------------------------------------------//
{ {
super (dataDisks[0]); super (dataDisks[0]);
@ -133,8 +137,10 @@ public class Wizardry4BootDisk extends PascalDisk
} }
} }
// ---------------------------------------------------------------------------------//
private void linkMonsterImages4 (DefaultMutableTreeNode monstersNode, private void linkMonsterImages4 (DefaultMutableTreeNode monstersNode,
FileEntry fileEntry) FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{ {
List<DiskAddress> pictureBlocks = fileEntry.getSectors (); List<DiskAddress> pictureBlocks = fileEntry.getSectors ();
@ -151,8 +157,10 @@ public class Wizardry4BootDisk extends PascalDisk
} }
} }
// ---------------------------------------------------------------------------------//
private void linkMonsterImages5 (DefaultMutableTreeNode monstersNode, private void linkMonsterImages5 (DefaultMutableTreeNode monstersNode,
FileEntry fileEntry) FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{ {
List<DiskAddress> pictureBlocks = fileEntry.getSectors (); List<DiskAddress> pictureBlocks = fileEntry.getSectors ();
@ -169,7 +177,9 @@ public class Wizardry4BootDisk extends PascalDisk
} }
} }
// ---------------------------------------------------------------------------------//
private void linkMazeLevels4 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry) private void linkMazeLevels4 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{ {
ScenarioData mazeData = scenarioHeader.data.get (Header.MAZE_AREA); ScenarioData mazeData = scenarioHeader.data.get (Header.MAZE_AREA);
@ -191,7 +201,9 @@ public class Wizardry4BootDisk extends PascalDisk
} }
} }
// ---------------------------------------------------------------------------------//
private void linkMazeLevels5 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry) private void linkMazeLevels5 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{ {
byte[] buffer = fileEntry.getDataSource ().buffer; byte[] buffer = fileEntry.getDataSource ().buffer;
List<DiskAddress> blocks = fileEntry.getSectors (); List<DiskAddress> blocks = fileEntry.getSectors ();
@ -221,7 +233,9 @@ public class Wizardry4BootDisk extends PascalDisk
afs.setSectors (allMazeBlocks); afs.setSectors (allMazeBlocks);
} }
// ---------------------------------------------------------------------------------//
private void linkBlock1 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry) private void linkBlock1 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{ {
byte[] buffer = fileEntry.getDataSource ().buffer; byte[] buffer = fileEntry.getDataSource ().buffer;
List<DiskAddress> blocks = fileEntry.getSectors (); List<DiskAddress> blocks = fileEntry.getSectors ();
@ -248,7 +262,9 @@ public class Wizardry4BootDisk extends PascalDisk
afs.setSectors (allBlocks); afs.setSectors (allBlocks);
} }
// ---------------------------------------------------------------------------------//
private void linkBlock2 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry) private void linkBlock2 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{ {
byte[] buffer = fileEntry.getDataSource ().buffer; byte[] buffer = fileEntry.getDataSource ().buffer;
List<DiskAddress> blocks = fileEntry.getSectors (); List<DiskAddress> blocks = fileEntry.getSectors ();
@ -275,7 +291,9 @@ public class Wizardry4BootDisk extends PascalDisk
afs.setSectors (allBlocks); afs.setSectors (allBlocks);
} }
// ---------------------------------------------------------------------------------//
private void linkOracle (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry) private void linkOracle (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{ {
byte[] buffer = fileEntry.getDataSource ().buffer; byte[] buffer = fileEntry.getDataSource ().buffer;
List<DiskAddress> blocks = fileEntry.getSectors (); List<DiskAddress> blocks = fileEntry.getSectors ();
@ -309,8 +327,10 @@ public class Wizardry4BootDisk extends PascalDisk
afs.setSectors (allOracleBlocks); afs.setSectors (allOracleBlocks);
} }
// ---------------------------------------------------------------------------------//
private void addToNode (AbstractFile af, DefaultMutableTreeNode node, private void addToNode (AbstractFile af, DefaultMutableTreeNode node,
List<DiskAddress> blocks) List<DiskAddress> blocks)
// ---------------------------------------------------------------------------------//
{ {
DefaultAppleFileSource dafs = DefaultAppleFileSource dafs =
new DefaultAppleFileSource (af.getName (), af, this, blocks); new DefaultAppleFileSource (af.getName (), af, this, blocks);
@ -319,8 +339,10 @@ public class Wizardry4BootDisk extends PascalDisk
node.add (childNode); node.add (childNode);
} }
// ---------------------------------------------------------------------------------//
private DefaultMutableTreeNode linkNode (String name, String text, private DefaultMutableTreeNode linkNode (String name, String text,
DefaultMutableTreeNode parent) DefaultMutableTreeNode parent)
// ---------------------------------------------------------------------------------//
{ {
DefaultAppleFileSource afs = new DefaultAppleFileSource (name, text, this); DefaultAppleFileSource afs = new DefaultAppleFileSource (name, text, this);
DefaultMutableTreeNode node = new DefaultMutableTreeNode (afs); DefaultMutableTreeNode node = new DefaultMutableTreeNode (afs);
@ -328,7 +350,9 @@ public class Wizardry4BootDisk extends PascalDisk
return node; return node;
} }
// ---------------------------------------------------------------------------------//
public static boolean isWizardryIVorV (Disk disk, boolean debug) public static boolean isWizardryIVorV (Disk disk, boolean debug)
// ---------------------------------------------------------------------------------//
{ {
// Wizardry IV or V boot code // Wizardry IV or V boot code
byte[] header = { 0x00, (byte) 0xEA, (byte) 0xA9, 0x60, (byte) 0x8D, 0x01, 0x08 }; byte[] header = { 0x00, (byte) 0xEA, (byte) 0xA9, 0x60, (byte) 0x8D, 0x01, 0x08 };

File diff suppressed because it is too large Load Diff