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;
import com.bytezone.diskbrowser.applefile.AbstractFile;
public abstract class AbstractImage extends AbstractFile
{
public AbstractImage (String name, byte[] buffer)
{
super (name, buffer);
}
package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.applefile.AbstractFile;
// -----------------------------------------------------------------------------------//
abstract class AbstractImage extends AbstractFile
// -----------------------------------------------------------------------------------//
{
// ---------------------------------------------------------------------------------//
AbstractImage (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
}
}

View File

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

View File

@ -1,44 +1,51 @@
package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.applefile.AbstractFile;
import com.bytezone.diskbrowser.utilities.HexFormatter;
class ExperienceLevel extends AbstractFile
{
private final long[] expLevels = new long[13];
public ExperienceLevel (String name, byte[] buffer)
{
super (name, buffer);
int seq = 0;
for (int ptr = 0; ptr < buffer.length; ptr += 6)
{
if (buffer[ptr] == 0)
break;
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];
}
@Override
public String getText ()
{
StringBuilder line = new StringBuilder ();
for (long exp : expLevels)
line.append (exp + "\n");
return line.toString ();
}
package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.applefile.AbstractFile;
import com.bytezone.diskbrowser.utilities.HexFormatter;
// -----------------------------------------------------------------------------------//
class ExperienceLevel extends AbstractFile
// -----------------------------------------------------------------------------------//
{
private final long[] expLevels = new long[13];
// ---------------------------------------------------------------------------------//
ExperienceLevel (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
int seq = 0;
for (int ptr = 0; ptr < buffer.length; ptr += 6)
{
if (buffer[ptr] == 0)
break;
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;
}
}
// ---------------------------------------------------------------------------------//
long getExperiencePoints (int level)
// ---------------------------------------------------------------------------------//
{
if (level < 13)
return expLevels[level];
return (level - 12) * expLevels[0] + expLevels[12];
}
// ---------------------------------------------------------------------------------//
@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;
import java.util.ArrayList;
import java.util.List;
import javax.swing.tree.DefaultMutableTreeNode;
import com.bytezone.diskbrowser.applefile.AppleFileSource;
import com.bytezone.diskbrowser.applefile.DefaultAppleFile;
import com.bytezone.diskbrowser.disk.DefaultAppleFileSource;
import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.disk.FormattedDisk;
import com.bytezone.diskbrowser.utilities.HexFormatter;
class Header
{
static String[] typeText = { "header", "maze", "monsters", "rewards", "items",
"characters", "images", "char levels" };
static String[] scenarioNames =
{ "PROVING GROUNDS OF THE MAD OVERLORD!", "THE KNIGHT OF DIAMONDS",
"THE LEGACY OF LLYLGAMYN", "THE RETURN OF WERDNA" };
static final int MAZE_AREA = 1;
static final int MONSTER_AREA = 2;
static final int TREASURE_TABLE_AREA = 3;
static final int ITEM_AREA = 4;
static final int CHARACTER_AREA = 5;
static final int IMAGE_AREA = 6;
static final int EXPERIENCE_AREA = 7;
String scenarioTitle;
public int scenarioID;
List<ScenarioData> data = new ArrayList<> (8);
FormattedDisk owner;
public Header (DefaultMutableTreeNode dataNode, FormattedDisk owner)
{
this.owner = owner;
AppleFileSource afs = (AppleFileSource) dataNode.getUserObject ();
List<DiskAddress> sectors = afs.getSectors ();
DefaultAppleFile daf = (DefaultAppleFile) afs.getDataSource ();
scenarioTitle = HexFormatter.getPascalString (daf.buffer, 0);
while (scenarioID < scenarioNames.length)
if (scenarioNames[scenarioID++].equals (scenarioTitle))
break;
if (scenarioID > scenarioNames.length)
System.out.println ("Invalid scenario ID : " + scenarioID + " " + scenarioTitle);
for (int i = 0; i < 8; i++)
data.add (new ScenarioData (daf.buffer, i, sectors));
StringBuilder text = new StringBuilder ("Data type Offset Size Units ???\n"
+ "------------ ------ ----- ----- -----\n");
for (ScenarioData sd : data)
text.append (sd + "\n");
daf.setText (text.toString ());
text = new StringBuilder (scenarioTitle + "\n\n");
int ptr = 106;
while (daf.buffer[ptr] != -1)
{
text.append (HexFormatter.getPascalString (daf.buffer, ptr) + "\n");
ptr += 10;
}
DefaultAppleFileSource dafs =
new DefaultAppleFileSource ("Header", text.toString (), owner);
dafs.setSectors (data.get (0).sectors);
DefaultMutableTreeNode headerNode = new DefaultMutableTreeNode (dafs);
dataNode.add (headerNode);
if (scenarioID > 3)
return;
int totalBlocks = data.get (0).sectors.size ();
linkText ("Text", data.get (0).sectors.get (0), headerNode);
if (scenarioID < 3)
{
linkPictures ("Alphabet", data.get (0).sectors.get (1), headerNode);
linkPictures ("Graphics", data.get (0).sectors.get (2), headerNode);
linkPictures ("Unknown", data.get (0).sectors.get (3), headerNode);
}
linkSpells ("Mage spells", data.get (0).sectors.get (totalBlocks - 2), headerNode);
linkSpells ("Priest spells", data.get (0).sectors.get (totalBlocks - 1), headerNode);
if (false && scenarioID <= 2)
{
System.out.println (printChars (daf.buffer, 1));
System.out.println (printChars (daf.buffer, 2));
}
}
private void linkText (String title, DiskAddress da, DefaultMutableTreeNode headerNode)
{
List<DiskAddress> blocks = new ArrayList<> ();
blocks.add (da);
StringBuilder text = new StringBuilder (scenarioTitle + "\n\n");
int ptr = 106;
byte[] buffer = owner.getDisk ().readSector (da);
while (buffer[ptr] != -1)
{
text.append (HexFormatter.getPascalString (buffer, ptr) + "\n");
ptr += 10;
}
ptr += 2;
text.append ("\n");
while (ptr < 512)
{
int value = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
text.append (String.format ("%04X %,6d%n", value, value));
ptr += 2;
}
DefaultAppleFileSource dafs =
new DefaultAppleFileSource (title, text.toString (), owner);
dafs.setSectors (blocks);
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
node.setAllowsChildren (false);
headerNode.add (node);
}
private void linkPictures (String title, DiskAddress da,
DefaultMutableTreeNode headerNode)
{
List<DiskAddress> blocks = new ArrayList<> ();
blocks.add (da);
byte[] buffer = owner.getDisk ().readSector (da);
String text = printChars (buffer, 0);
DefaultAppleFileSource dafs = new DefaultAppleFileSource (title, text, owner);
dafs.setSectors (blocks);
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
node.setAllowsChildren (false);
headerNode.add (node);
}
private void linkSpells (String title, DiskAddress da,
DefaultMutableTreeNode headerNode)
{
List<DiskAddress> blocks = new ArrayList<> ();
blocks.add (da);
int level = 1;
StringBuilder list = new StringBuilder ("Level " + level + ":\n");
byte[] buffer = owner.getDisk ().readSector (da);
String text = HexFormatter.getString (buffer, 0, 512);
String[] spells = text.split ("\n");
for (String s : spells)
{
if (s.length () == 0)
break;
if (s.startsWith ("*"))
{
s = s.substring (1);
level++;
list.append ("\nLevel " + level + ":\n");
}
list.append (" " + s + "\n");
}
DefaultAppleFileSource dafs =
new DefaultAppleFileSource (title, list.toString (), owner);
dafs.setSectors (blocks);
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
node.setAllowsChildren (false);
headerNode.add (node);
}
private String printChars (byte[] buffer, int block)
{
StringBuilder text = new StringBuilder ();
for (int i = block * 512; i < (block + 1) * 512; i += 64)
{
for (int line = 0; line < 8; line++)
{
for (int j = 0; j < 8; j++)
{
int value = buffer[i + line + j * 8] & 0xFF;
for (int bit = 0; bit < 7; bit++)
{
if ((value & 0x01) == 1)
text.append ("O");
else
text.append (".");
value >>= 1;
}
text.append (" ");
}
text.append ("\n");
}
text.append ("\n");
}
return text.toString ();
}
// this could be the base factory class for all Wizardry types
class ScenarioData
{
int dunno;
int total;
int totalBlocks;
int dataOffset;
int type;
List<DiskAddress> sectors;
public ScenarioData (byte[] buffer, int seq, List<DiskAddress> sectors)
{
int offset = 42 + seq * 2;
dunno = buffer[offset] & 0xFF;
total = buffer[offset + 16] & 0xFF;
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);
}
}
package com.bytezone.diskbrowser.wizardry;
import java.util.ArrayList;
import java.util.List;
import javax.swing.tree.DefaultMutableTreeNode;
import com.bytezone.diskbrowser.applefile.AppleFileSource;
import com.bytezone.diskbrowser.applefile.DefaultAppleFile;
import com.bytezone.diskbrowser.disk.DefaultAppleFileSource;
import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.disk.FormattedDisk;
import com.bytezone.diskbrowser.utilities.HexFormatter;
// -----------------------------------------------------------------------------------//
class Header
// -----------------------------------------------------------------------------------//
{
static String[] typeText = { "header", "maze", "monsters", "rewards", "items",
"characters", "images", "char levels" };
static String[] scenarioNames =
{ "PROVING GROUNDS OF THE MAD OVERLORD!", "THE KNIGHT OF DIAMONDS",
"THE LEGACY OF LLYLGAMYN", "THE RETURN OF WERDNA" };
static final int MAZE_AREA = 1;
static final int MONSTER_AREA = 2;
static final int TREASURE_TABLE_AREA = 3;
static final int ITEM_AREA = 4;
static final int CHARACTER_AREA = 5;
static final int IMAGE_AREA = 6;
static final int EXPERIENCE_AREA = 7;
String scenarioTitle;
public int scenarioID;
List<ScenarioData> data = new ArrayList<> (8);
FormattedDisk owner;
// ---------------------------------------------------------------------------------//
Header (DefaultMutableTreeNode dataNode, FormattedDisk owner)
// ---------------------------------------------------------------------------------//
{
this.owner = owner;
AppleFileSource afs = (AppleFileSource) dataNode.getUserObject ();
List<DiskAddress> sectors = afs.getSectors ();
DefaultAppleFile daf = (DefaultAppleFile) afs.getDataSource ();
scenarioTitle = HexFormatter.getPascalString (daf.buffer, 0);
while (scenarioID < scenarioNames.length)
if (scenarioNames[scenarioID++].equals (scenarioTitle))
break;
if (scenarioID > scenarioNames.length)
System.out.println ("Invalid scenario ID : " + scenarioID + " " + scenarioTitle);
for (int i = 0; i < 8; i++)
data.add (new ScenarioData (daf.buffer, i, sectors));
StringBuilder text = new StringBuilder ("Data type Offset Size Units ???\n"
+ "------------ ------ ----- ----- -----\n");
for (ScenarioData sd : data)
text.append (sd + "\n");
daf.setText (text.toString ());
text = new StringBuilder (scenarioTitle + "\n\n");
int ptr = 106;
while (daf.buffer[ptr] != -1)
{
text.append (HexFormatter.getPascalString (daf.buffer, ptr) + "\n");
ptr += 10;
}
DefaultAppleFileSource dafs =
new DefaultAppleFileSource ("Header", text.toString (), owner);
dafs.setSectors (data.get (0).sectors);
DefaultMutableTreeNode headerNode = new DefaultMutableTreeNode (dafs);
dataNode.add (headerNode);
if (scenarioID > 3)
return;
int totalBlocks = data.get (0).sectors.size ();
linkText ("Text", data.get (0).sectors.get (0), headerNode);
if (scenarioID < 3)
{
linkPictures ("Alphabet", data.get (0).sectors.get (1), headerNode);
linkPictures ("Graphics", data.get (0).sectors.get (2), headerNode);
linkPictures ("Unknown", data.get (0).sectors.get (3), headerNode);
}
linkSpells ("Mage spells", data.get (0).sectors.get (totalBlocks - 2), headerNode);
linkSpells ("Priest spells", data.get (0).sectors.get (totalBlocks - 1), headerNode);
if (false && scenarioID <= 2)
{
System.out.println (printChars (daf.buffer, 1));
System.out.println (printChars (daf.buffer, 2));
}
}
// ---------------------------------------------------------------------------------//
private void linkText (String title, DiskAddress da, DefaultMutableTreeNode headerNode)
// ---------------------------------------------------------------------------------//
{
List<DiskAddress> blocks = new ArrayList<> ();
blocks.add (da);
StringBuilder text = new StringBuilder (scenarioTitle + "\n\n");
int ptr = 106;
byte[] buffer = owner.getDisk ().readSector (da);
while (buffer[ptr] != -1)
{
text.append (HexFormatter.getPascalString (buffer, ptr) + "\n");
ptr += 10;
}
ptr += 2;
text.append ("\n");
while (ptr < 512)
{
int value = HexFormatter.intValue (buffer[ptr], buffer[ptr + 1]);
text.append (String.format ("%04X %,6d%n", value, value));
ptr += 2;
}
DefaultAppleFileSource dafs =
new DefaultAppleFileSource (title, text.toString (), owner);
dafs.setSectors (blocks);
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
node.setAllowsChildren (false);
headerNode.add (node);
}
// ---------------------------------------------------------------------------------//
private void linkPictures (String title, DiskAddress da,
DefaultMutableTreeNode headerNode)
// ---------------------------------------------------------------------------------//
{
List<DiskAddress> blocks = new ArrayList<> ();
blocks.add (da);
byte[] buffer = owner.getDisk ().readSector (da);
String text = printChars (buffer, 0);
DefaultAppleFileSource dafs = new DefaultAppleFileSource (title, text, owner);
dafs.setSectors (blocks);
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
node.setAllowsChildren (false);
headerNode.add (node);
}
// ---------------------------------------------------------------------------------//
private void linkSpells (String title, DiskAddress da,
DefaultMutableTreeNode headerNode)
// ---------------------------------------------------------------------------------//
{
List<DiskAddress> blocks = new ArrayList<> ();
blocks.add (da);
int level = 1;
StringBuilder list = new StringBuilder ("Level " + level + ":\n");
byte[] buffer = owner.getDisk ().readSector (da);
String text = HexFormatter.getString (buffer, 0, 512);
String[] spells = text.split ("\n");
for (String s : spells)
{
if (s.length () == 0)
break;
if (s.startsWith ("*"))
{
s = s.substring (1);
level++;
list.append ("\nLevel " + level + ":\n");
}
list.append (" " + s + "\n");
}
DefaultAppleFileSource dafs =
new DefaultAppleFileSource (title, list.toString (), owner);
dafs.setSectors (blocks);
DefaultMutableTreeNode node = new DefaultMutableTreeNode (dafs);
node.setAllowsChildren (false);
headerNode.add (node);
}
// ---------------------------------------------------------------------------------//
private String printChars (byte[] buffer, int block)
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
for (int i = block * 512; i < (block + 1) * 512; i += 64)
{
for (int line = 0; line < 8; line++)
{
for (int j = 0; j < 8; j++)
{
int value = buffer[i + line + j * 8] & 0xFF;
for (int bit = 0; bit < 7; bit++)
{
if ((value & 0x01) == 1)
text.append ("O");
else
text.append (".");
value >>= 1;
}
text.append (" ");
}
text.append ("\n");
}
text.append ("\n");
}
return text.toString ();
}
// this could be the base factory class for all Wizardry types
// ---------------------------------------------------------------------------------//
class ScenarioData
// ---------------------------------------------------------------------------------//
{
int dunno;
int total;
int totalBlocks;
int dataOffset;
int type;
List<DiskAddress> sectors;
public ScenarioData (byte[] buffer, int seq, List<DiskAddress> sectors)
{
int offset = 42 + seq * 2;
dunno = buffer[offset] & 0xFF;
total = buffer[offset + 16] & 0xFF;
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:
// 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 int[] offset = { 512, 256 }; // offset to left/right nodes
@ -19,12 +21,16 @@ public class Huffman extends AbstractFile
private String bufferContents;
public Huffman (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
Huffman (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
}
public String decodeMessage (byte[] message)
// ---------------------------------------------------------------------------------//
String decodeMessage (byte[] message)
// ---------------------------------------------------------------------------------//
{
this.message = message;
depth = 0;
@ -39,7 +45,9 @@ public class Huffman extends AbstractFile
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private byte getChar ()
// ---------------------------------------------------------------------------------//
{
int treePtr = 0; // start at the root
@ -63,8 +71,10 @@ public class Huffman extends AbstractFile
}
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
if (bufferContents == null)
{
@ -75,7 +85,9 @@ public class Huffman extends AbstractFile
return bufferContents;
}
// ---------------------------------------------------------------------------------//
private void walk (int treePtr, String path, StringBuilder text)
// ---------------------------------------------------------------------------------//
{
for (int currentBit = 1; currentBit >= 0; --currentBit)
if ((buffer[treePtr] & mask[currentBit]) == 0)

View File

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

View File

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

View File

@ -1,328 +1,370 @@
package com.bytezone.diskbrowser.wizardry;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.util.List;
import com.bytezone.diskbrowser.utilities.HexFormatter;
class MazeCell
{
static Dimension cellSize = new Dimension (22, 22); // size in pixels
boolean northWall;
boolean southWall;
boolean eastWall;
boolean westWall;
boolean northDoor;
boolean southDoor;
boolean eastDoor;
boolean westDoor;
boolean darkness;
boolean stairs;
boolean pit;
boolean spinner;
boolean chute;
boolean elevator;
boolean monsterLair;
boolean rock;
boolean teleport;
boolean spellsBlocked;
int elevatorFrom;
int elevatorTo;
int messageType;
int monsterID = -1;
int itemID;
int unknown;
MazeAddress address;
MazeAddress addressTo; // if teleport/stairs/chute
public Message message;
public List<Monster> monsters;
public Item itemRequired;
public Item itemObtained;
public MazeCell (MazeAddress address)
{
this.address = address;
}
public void draw (Graphics2D g, int x, int y)
{
g.setColor (Color.BLACK);
g.fillRect (x, y, 22, 22);
g.setColor (Color.WHITE);
if (westWall)
drawWest (g, x, y);
if (eastWall)
drawEast (g, x, y);
if (northWall)
drawNorth (g, x, y);
if (southWall)
drawSouth (g, x, y);
g.setColor (Color.RED);
if (westDoor)
drawWest (g, x, y);
if (eastDoor)
drawEast (g, x, y);
if (northDoor)
drawNorth (g, x, y);
if (southDoor)
drawSouth (g, x, y);
g.setColor (Color.GREEN);
if (westDoor && westWall)
drawWest (g, x, y);
if (eastDoor && eastWall)
drawEast (g, x, y);
if (northDoor && northWall)
drawNorth (g, x, y);
if (southDoor && southWall)
drawSouth (g, x, y);
g.setColor (Color.WHITE);
if (monsterLair)
drawMonsterLair (g, x, y);
if (stairs)
if (address.level < addressTo.level)
drawStairsDown (g, x, y);
else
drawStairsUp (g, x, y);
else if (message != null)
drawChar (g, x, y, "M", Color.RED);
else if (pit)
drawPit (g, x, y);
else if (chute)
drawChute (g, x, y);
else if (spinner)
g.drawString ("S", x + 8, y + 16);
else if (teleport)
drawTeleport (g, x, y);
else if (darkness)
drawDarkness (g, x, y);
else if (rock)
drawRock (g, x, y);
else if (elevator)
drawElevator (g, x, y, (elevatorTo - elevatorFrom + 1) / 2);
else if (monsterID >= 0)
drawMonster (g, x, y);
else if (spellsBlocked)
drawSpellsBlocked (g, x, y);
else if (unknown != 0)
drawChar (g, x, y, HexFormatter.format1 (unknown), Color.GRAY);
}
public void drawWest (Graphics2D g, int x, int y)
{
g.drawLine (x + 1, y + 1, x + 1, y + cellSize.height - 1);
}
private void drawEast (Graphics2D g, int x, int y)
{
g.drawLine (x + cellSize.width - 1, y + 1, x + cellSize.width - 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);
}
private void drawSouth (Graphics2D g, int x, int y)
{
g.drawLine (x + 1, y + cellSize.height - 1, x + cellSize.width - 1,
y + cellSize.height - 1);
}
public void drawStairsUp (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 + 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);
}
public void drawStairsDown (Graphics2D g, int x, int y)
{
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);
g.drawLine (x + 12, y + 15, x + 16, y + 15);
g.drawLine (x + 16, y + 15, x + 16, y + 19);
}
public void drawPit (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.drawLine (x + 17, y + 14, x + 17, y + 19);
}
public void drawChute (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);
}
public void drawElevator (Graphics2D g, int x, int y, int rows)
{
for (int i = 0; i < rows; i++)
{
g.drawOval (x + 7, y + i * 5 + 5, 2, 2);
g.drawOval (x + 14, y + i * 5 + 5, 2, 2);
}
}
public void drawMonsterLair (Graphics2D g, int x, int y)
{
g.setColor (Color.YELLOW);
g.fillOval (x + 4, y + 4, 2, 2);
g.setColor (Color.WHITE);
}
public void drawTeleport (Graphics2D g, int x, int y)
{
g.setColor (Color.GREEN);
g.fillOval (x + 8, y + 8, 8, 8);
g.setColor (Color.WHITE);
}
public void drawSpellsBlocked (Graphics2D g, int x, int y)
{
g.setColor (Color.YELLOW);
g.fillOval (x + 8, y + 8, 8, 8);
g.setColor (Color.WHITE);
}
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);
}
public void drawDarkness (Graphics2D g, int x, int y)
{
g.setColor (Color.gray);
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);
}
public void drawRock (Graphics2D g, int x, int y)
{
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);
}
public void drawChar (Graphics2D g, int x, int y, String c, Color colour)
{
g.setColor (colour);
g.fillRect (x + 7, y + 6, 11, 11);
g.setColor (Color.WHITE);
g.drawString (c, x + 8, y + 16);
}
public void drawHotDogStand (Graphics2D g, int x, int y)
{
g.drawRect (x + 5, y + 11, 12, 6);
g.drawOval (x + 6, y + 18, 3, 3);
g.drawOval (x + 13, y + 18, 3, 3);
g.drawLine (x + 8, y + 6, x + 8, y + 10);
g.drawLine (x + 14, y + 6, x + 14, y + 10);
g.drawLine (x + 5, y + 5, x + 17, y + 5);
}
public String getTooltipText ()
{
StringBuilder sign = new StringBuilder ("<html><pre>");
sign.append ("&nbsp;<b>");
sign.append (address.row + "N ");
sign.append (address.column + "E</b>&nbsp;<br>");
if (message != null)
sign.append (message.toHTMLString ());
if (elevator)
sign.append ("&nbsp;Elevator: L" + elevatorFrom + "-L" + elevatorTo + "&nbsp;");
if (stairs)
{
sign.append ("&nbsp;Stairs to ");
if (addressTo.level == 0)
sign.append ("castle&nbsp;");
else
{
sign.append ("level " + addressTo.level + "&nbsp;");
}
}
if (teleport)
{
sign.append ("&nbsp;Teleport to ");
if (addressTo.level == 0)
sign.append ("castle&nbsp;");
else
{
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 ();
}
package com.bytezone.diskbrowser.wizardry;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.util.List;
import com.bytezone.diskbrowser.utilities.HexFormatter;
// -----------------------------------------------------------------------------------//
class MazeCell
// -----------------------------------------------------------------------------------//
{
static Dimension cellSize = new Dimension (22, 22); // size in pixels
boolean northWall;
boolean southWall;
boolean eastWall;
boolean westWall;
boolean northDoor;
boolean southDoor;
boolean eastDoor;
boolean westDoor;
boolean darkness;
boolean stairs;
boolean pit;
boolean spinner;
boolean chute;
boolean elevator;
boolean monsterLair;
boolean rock;
boolean teleport;
boolean spellsBlocked;
int elevatorFrom;
int elevatorTo;
int messageType;
int monsterID = -1;
int itemID;
int unknown;
MazeAddress address;
MazeAddress addressTo; // if teleport/stairs/chute
public Message message;
public List<Monster> monsters;
public Item itemRequired;
public Item itemObtained;
// ---------------------------------------------------------------------------------//
MazeCell (MazeAddress address)
// ---------------------------------------------------------------------------------//
{
this.address = address;
}
// ---------------------------------------------------------------------------------//
void draw (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
{
g.setColor (Color.BLACK);
g.fillRect (x, y, 22, 22);
g.setColor (Color.WHITE);
if (westWall)
drawWest (g, x, y);
if (eastWall)
drawEast (g, x, y);
if (northWall)
drawNorth (g, x, y);
if (southWall)
drawSouth (g, x, y);
g.setColor (Color.RED);
if (westDoor)
drawWest (g, x, y);
if (eastDoor)
drawEast (g, x, y);
if (northDoor)
drawNorth (g, x, y);
if (southDoor)
drawSouth (g, x, y);
g.setColor (Color.GREEN);
if (westDoor && westWall)
drawWest (g, x, y);
if (eastDoor && eastWall)
drawEast (g, x, y);
if (northDoor && northWall)
drawNorth (g, x, y);
if (southDoor && southWall)
drawSouth (g, x, y);
g.setColor (Color.WHITE);
if (monsterLair)
drawMonsterLair (g, x, y);
if (stairs)
if (address.level < addressTo.level)
drawStairsDown (g, x, y);
else
drawStairsUp (g, x, y);
else if (message != null)
drawChar (g, x, y, "M", Color.RED);
else if (pit)
drawPit (g, x, y);
else if (chute)
drawChute (g, x, y);
else if (spinner)
g.drawString ("S", x + 8, y + 16);
else if (teleport)
drawTeleport (g, x, y);
else if (darkness)
drawDarkness (g, x, y);
else if (rock)
drawRock (g, x, y);
else if (elevator)
drawElevator (g, x, y, (elevatorTo - elevatorFrom + 1) / 2);
else if (monsterID >= 0)
drawMonster (g, x, y);
else if (spellsBlocked)
drawSpellsBlocked (g, x, y);
else if (unknown != 0)
drawChar (g, x, y, HexFormatter.format1 (unknown), Color.GRAY);
}
// ---------------------------------------------------------------------------------//
void drawWest (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
{
g.drawLine (x + 1, y + 1, x + 1, y + cellSize.height - 1);
}
// ---------------------------------------------------------------------------------//
void drawEast (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
{
g.drawLine (x + cellSize.width - 1, y + 1, x + cellSize.width - 1,
y + cellSize.height - 1);
}
// ---------------------------------------------------------------------------------//
void drawNorth (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
{
g.drawLine (x + 1, y + 1, x + cellSize.width - 1, y + 1);
}
// ---------------------------------------------------------------------------------//
void drawSouth (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
{
g.drawLine (x + 1, y + cellSize.height - 1, x + cellSize.width - 1,
y + cellSize.height - 1);
}
// ---------------------------------------------------------------------------------//
void drawStairsUp (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 + 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 drawStairsDown (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
{
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);
g.drawLine (x + 12, y + 15, x + 16, y + 15);
g.drawLine (x + 16, y + 15, x + 16, y + 19);
}
// ---------------------------------------------------------------------------------//
void drawPit (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.drawLine (x + 17, y + 14, x + 17, y + 19);
}
// ---------------------------------------------------------------------------------//
void drawChute (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);
}
// ---------------------------------------------------------------------------------//
void drawElevator (Graphics2D g, int x, int y, int rows)
// ---------------------------------------------------------------------------------//
{
for (int i = 0; i < rows; i++)
{
g.drawOval (x + 7, y + i * 5 + 5, 2, 2);
g.drawOval (x + 14, y + i * 5 + 5, 2, 2);
}
}
// ---------------------------------------------------------------------------------//
void drawMonsterLair (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
{
g.setColor (Color.YELLOW);
g.fillOval (x + 4, y + 4, 2, 2);
g.setColor (Color.WHITE);
}
// ---------------------------------------------------------------------------------//
void drawTeleport (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
{
g.setColor (Color.GREEN);
g.fillOval (x + 8, y + 8, 8, 8);
g.setColor (Color.WHITE);
}
// ---------------------------------------------------------------------------------//
void drawSpellsBlocked (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
{
g.setColor (Color.YELLOW);
g.fillOval (x + 8, y + 8, 8, 8);
g.setColor (Color.WHITE);
}
// ---------------------------------------------------------------------------------//
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 drawDarkness (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
{
g.setColor (Color.gray);
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 drawRock (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
{
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);
}
// ---------------------------------------------------------------------------------//
void drawChar (Graphics2D g, int x, int y, String c, Color colour)
// ---------------------------------------------------------------------------------//
{
g.setColor (colour);
g.fillRect (x + 7, y + 6, 11, 11);
g.setColor (Color.WHITE);
g.drawString (c, x + 8, y + 16);
}
// ---------------------------------------------------------------------------------//
void drawHotDogStand (Graphics2D g, int x, int y)
// ---------------------------------------------------------------------------------//
{
g.drawRect (x + 5, y + 11, 12, 6);
g.drawOval (x + 6, y + 18, 3, 3);
g.drawOval (x + 13, y + 18, 3, 3);
g.drawLine (x + 8, y + 6, x + 8, y + 10);
g.drawLine (x + 14, y + 6, x + 14, y + 10);
g.drawLine (x + 5, y + 5, x + 17, y + 5);
}
// ---------------------------------------------------------------------------------//
String getTooltipText ()
// ---------------------------------------------------------------------------------//
{
StringBuilder sign = new StringBuilder ("<html><pre>");
sign.append ("&nbsp;<b>");
sign.append (address.row + "N ");
sign.append (address.column + "E</b>&nbsp;<br>");
if (message != null)
sign.append (message.toHTMLString ());
if (elevator)
sign.append ("&nbsp;Elevator: L" + elevatorFrom + "-L" + elevatorTo + "&nbsp;");
if (stairs)
{
sign.append ("&nbsp;Stairs to ");
if (addressTo.level == 0)
sign.append ("castle&nbsp;");
else
{
sign.append ("level " + addressTo.level + "&nbsp;");
}
}
if (teleport)
{
sign.append ("&nbsp;Teleport to ");
if (addressTo.level == 0)
sign.append ("castle&nbsp;");
else
{
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.utilities.HexFormatter;
public class MazeGridV5 extends AbstractFile
// -----------------------------------------------------------------------------------//
class MazeGridV5 extends AbstractFile
// -----------------------------------------------------------------------------------//
{
private final MessageBlock messageBlock;
List<MazeGrid> grids = new ArrayList<> ();
@ -21,7 +23,9 @@ public class MazeGridV5 extends AbstractFile
int maxX = 0;
int maxY = 0;
public MazeGridV5 (String name, byte[] buffer, MessageBlock messageBlock)
// ---------------------------------------------------------------------------------//
MazeGridV5 (String name, byte[] buffer, MessageBlock messageBlock)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
@ -45,8 +49,10 @@ public class MazeGridV5 extends AbstractFile
}
}
// ---------------------------------------------------------------------------------//
@Override
public BufferedImage getImage ()
// ---------------------------------------------------------------------------------//
{
Dimension cellSize = new Dimension (22, 22);
int fudge = 30;
@ -80,7 +86,9 @@ public class MazeGridV5 extends AbstractFile
return image;
}
// ---------------------------------------------------------------------------------//
private MazeCell getLayout (int gridNo, int row, int column)
// ---------------------------------------------------------------------------------//
{
MazeAddress address = new MazeAddress (0, row, column);
MazeCell cell = new MazeCell (address);
@ -103,8 +111,10 @@ public class MazeGridV5 extends AbstractFile
return cell;
}
// ---------------------------------------------------------------------------------//
@Override
public String getHexDump ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder (super.getHexDump ());
@ -187,7 +197,9 @@ public class MazeGridV5 extends AbstractFile
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private class MazeGrid
// ---------------------------------------------------------------------------------//
{
MazeCell[][] grid;
int xOffset;

File diff suppressed because it is too large Load Diff

View File

@ -1,71 +1,85 @@
package com.bytezone.diskbrowser.wizardry;
import java.util.ArrayList;
import java.util.List;
import com.bytezone.diskbrowser.applefile.AbstractFile;
abstract class Message extends AbstractFile
{
private static int nextId = 0;
protected String message;
private final int id;
private int totalLines;
List<String> lines = new ArrayList<> ();
public Message (byte[] buffer)
{
super ("Message " + nextId, buffer);
this.id = nextId;
int recordLength = 42;
StringBuilder text = new StringBuilder ();
for (int ptr = 0; ptr < buffer.length; ptr += recordLength)
{
nextId++;
totalLines++;
String line = getLine (ptr);
text.append (line + "\n");
lines.add (line);
}
text.deleteCharAt (text.length () - 1);
message = text.toString ();
}
protected abstract String getLine (int offset);
public boolean match (int messageNum)
{
if (id == messageNum)
return true;
// this code is to allow for a bug in scenario #1
if (messageNum > id && messageNum < (id + totalLines))
return true;
return false;
}
@Override
public String getText ()
{
return message;
}
public String toHTMLString ()
{
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;
}
package com.bytezone.diskbrowser.wizardry;
import java.util.ArrayList;
import java.util.List;
import com.bytezone.diskbrowser.applefile.AbstractFile;
// -----------------------------------------------------------------------------------//
abstract class Message extends AbstractFile
// -----------------------------------------------------------------------------------//
{
private static int nextId = 0;
protected String message;
private final int id;
private int totalLines;
List<String> lines = new ArrayList<> ();
// ---------------------------------------------------------------------------------//
Message (byte[] buffer)
// ---------------------------------------------------------------------------------//
{
super ("Message " + nextId, buffer);
this.id = nextId;
int recordLength = 42;
StringBuilder text = new StringBuilder ();
for (int ptr = 0; ptr < buffer.length; ptr += recordLength)
{
nextId++;
totalLines++;
String line = getLine (ptr);
text.append (line + "\n");
lines.add (line);
}
text.deleteCharAt (text.length () - 1);
message = text.toString ();
}
// ---------------------------------------------------------------------------------//
protected abstract String getLine (int offset);
// ---------------------------------------------------------------------------------//
// ---------------------------------------------------------------------------------//
public boolean match (int messageNum)
// ---------------------------------------------------------------------------------//
{
if (id == messageNum)
return true;
// this code is to allow for a bug in scenario #1
if (messageNum > id && messageNum < (id + totalLines))
return true;
return false;
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
return message;
}
// ---------------------------------------------------------------------------------//
public String toHTMLString ()
// ---------------------------------------------------------------------------------//
{
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.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 indexLength;
@ -15,7 +17,9 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
private final List<MessageDataBlock> messageDataBlocks = new ArrayList<> ();
public MessageBlock (byte[] buffer, Huffman huffman)
// ---------------------------------------------------------------------------------//
MessageBlock (byte[] buffer, Huffman huffman)
// ---------------------------------------------------------------------------------//
{
super ("bollocks", buffer);
@ -35,7 +39,9 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
}
}
// ---------------------------------------------------------------------------------//
public String getMessageText (int messageNo)
// ---------------------------------------------------------------------------------//
{
for (int i = 0; i < messageDataBlocks.size (); i++)
{
@ -46,7 +52,9 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
return null;
}
// ---------------------------------------------------------------------------------//
public List<String> getMessageLines (int messageNo)
// ---------------------------------------------------------------------------------//
{
List<String> lines = new ArrayList<> ();
@ -72,7 +80,9 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
return lines;
}
// ---------------------------------------------------------------------------------//
public byte[] getMessage (int messageNo)
// ---------------------------------------------------------------------------------//
{
for (int i = 0; i < messageDataBlocks.size (); i++)
{
@ -83,8 +93,10 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
return null;
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
if (text != null)
return text;
@ -102,8 +114,10 @@ public class MessageBlock extends AbstractFile implements Iterable<MessageDataBl
return this.text;
}
// ---------------------------------------------------------------------------------//
@Override
public Iterator<MessageDataBlock> iterator ()
// ---------------------------------------------------------------------------------//
{
return messageDataBlocks.iterator ();
}

View File

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

View File

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

View File

@ -1,141 +1,155 @@
package com.bytezone.diskbrowser.wizardry;
import java.util.ArrayList;
import java.util.List;
import com.bytezone.diskbrowser.applefile.AbstractFile;
class Reward extends AbstractFile
{
static String[] types = { "gold", "item" };
static final int SEGMENT_LENGTH = 18;
int id;
int totalElements;
List<RewardElement> elements;
List<Item> items;
List<Monster> goldMonsters = new ArrayList<> ();
List<Monster> chestMonsters = new ArrayList<> ();
public Reward (String name, byte[] buffer, int id, List<Item> items)
{
super (name, buffer);
this.id = id;
this.items = items;
totalElements = buffer[4];
elements = new ArrayList<> (totalElements);
for (int i = 0; i < totalElements; i++)
{
byte[] buffer2 = new byte[SEGMENT_LENGTH];
System.arraycopy (buffer, i * SEGMENT_LENGTH, buffer2, 0, SEGMENT_LENGTH);
elements.add (new RewardElement (buffer2));
}
}
public void addMonster (Monster monster, int location)
{
if (location == 0)
goldMonsters.add (monster);
else
chestMonsters.add (monster);
}
@Override
public String getText ()
{
return getText (true);
}
public String getText (boolean showLinks)
{
StringBuilder text = new StringBuilder ();
for (RewardElement re : elements)
text.append (re.getDetail () + "\n");
if (showLinks)
{
if (goldMonsters.size () > 0)
{
text.append ("Without chest:\n\n");
for (Monster m : goldMonsters)
text.append (" " + m + "\n");
text.append ("\n");
}
if (chestMonsters.size () > 0)
{
text.append ("With chest:\n\n");
for (Monster m : chestMonsters)
text.append (" " + m + "\n");
}
}
return text.toString ();
}
public String getDump ()
{
StringBuilder text = new StringBuilder ();
int seq = 0;
for (RewardElement re : elements)
{
text.append (seq++ == 0 ? String.format ("%02X : ", id) : " ");
text.append (re + "\n");
}
return text.toString ();
}
private class RewardElement
{
int type;
int odds;
byte[] buffer;
public RewardElement (byte[] buffer)
{
this.buffer = buffer;
type = buffer[8];
odds = buffer[6];
}
@Override
public String toString ()
{
StringBuilder text = new StringBuilder ();
for (int i = 0; i < SEGMENT_LENGTH; i += 2)
text.append (String.format ("%3d ", buffer[i] & 0xFF));
return text.toString ();
}
public String getDetail ()
{
StringBuilder text = new StringBuilder ();
text.append ("Odds ............ " + odds + "%\n");
switch (type)
{
case 0:
text.append ("Gold ............ " + buffer[10] + "d" + buffer[12] + "\n");
break;
case 1:
int lo = buffer[10] & 0xFF;
int qty = buffer[16] & 0xFF;
boolean title = true;
String[] lineItem = new String[4];
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 ();
}
}
package com.bytezone.diskbrowser.wizardry;
import java.util.ArrayList;
import java.util.List;
import com.bytezone.diskbrowser.applefile.AbstractFile;
// -----------------------------------------------------------------------------------//
class Reward extends AbstractFile
// -----------------------------------------------------------------------------------//
{
static String[] types = { "gold", "item" };
static final int SEGMENT_LENGTH = 18;
int id;
int totalElements;
List<RewardElement> elements;
List<Item> items;
List<Monster> goldMonsters = new ArrayList<> ();
List<Monster> chestMonsters = new ArrayList<> ();
// ---------------------------------------------------------------------------------//
Reward (String name, byte[] buffer, int id, List<Item> items)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
this.id = id;
this.items = items;
totalElements = buffer[4];
elements = new ArrayList<> (totalElements);
for (int i = 0; i < totalElements; i++)
{
byte[] buffer2 = new byte[SEGMENT_LENGTH];
System.arraycopy (buffer, i * SEGMENT_LENGTH, buffer2, 0, SEGMENT_LENGTH);
elements.add (new RewardElement (buffer2));
}
}
// ---------------------------------------------------------------------------------//
public void addMonster (Monster monster, int location)
// ---------------------------------------------------------------------------------//
{
if (location == 0)
goldMonsters.add (monster);
else
chestMonsters.add (monster);
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
return getText (true);
}
// ---------------------------------------------------------------------------------//
public String getText (boolean showLinks)
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
for (RewardElement re : elements)
text.append (re.getDetail () + "\n");
if (showLinks)
{
if (goldMonsters.size () > 0)
{
text.append ("Without chest:\n\n");
for (Monster m : goldMonsters)
text.append (" " + m + "\n");
text.append ("\n");
}
if (chestMonsters.size () > 0)
{
text.append ("With chest:\n\n");
for (Monster m : chestMonsters)
text.append (" " + m + "\n");
}
}
return text.toString ();
}
// ---------------------------------------------------------------------------------//
public String getDump ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
int seq = 0;
for (RewardElement re : elements)
{
text.append (seq++ == 0 ? String.format ("%02X : ", id) : " ");
text.append (re + "\n");
}
return text.toString ();
}
// ---------------------------------------------------------------------------------//
private class RewardElement
// ---------------------------------------------------------------------------------//
{
int type;
int odds;
byte[] buffer;
public RewardElement (byte[] buffer)
{
this.buffer = buffer;
type = buffer[8];
odds = buffer[6];
}
@Override
public String toString ()
{
StringBuilder text = new StringBuilder ();
for (int i = 0; i < SEGMENT_LENGTH; i += 2)
text.append (String.format ("%3d ", buffer[i] & 0xFF));
return text.toString ();
}
public String getDetail ()
{
StringBuilder text = new StringBuilder ();
text.append ("Odds ............ " + odds + "%\n");
switch (type)
{
case 0:
text.append ("Gold ............ " + buffer[10] + "d" + buffer[12] + "\n");
break;
case 1:
int lo = buffer[10] & 0xFF;
int qty = buffer[16] & 0xFF;
boolean title = true;
String[] lineItem = new String[4];
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;
import com.bytezone.diskbrowser.applefile.AbstractFile;
class Spell extends AbstractFile
{
private final SpellType spellType;
private SpellThrown whenCast;
private final int level;
private String translation;
private SpellTarget target;
private String description;
public enum SpellType {
MAGE, PRIEST
};
public enum SpellTarget {
PERSON, PARTY, MONSTER, MONSTER_GROUP, ALL_MONSTERS, VARIABLE, NONE, CASTER
};
public enum SpellThrown {
COMBAT, ANY_TIME, LOOTING, CAMP, COMBAT_OR_CAMP
};
private static int lastSpellFound = -1;
private Spell (String spellName, SpellType type, int level, byte[] buffer)
{
super (spellName, buffer);
this.spellType = type;
this.level = level;
if (lastSpellFound + 1 < spellNames.length && spellName.equals (spellNames[lastSpellFound + 1]))
setSpell (++lastSpellFound);
else
{
for (int i = 0; i < spellNames.length; i++)
if (spellName.equals (spellNames[i]))
{
setSpell (i);
lastSpellFound = i;
break;
}
}
}
private void setSpell (int spellNo)
{
this.translation = translations[spellNo];
this.description = descriptions[spellNo];
this.whenCast = when[spellNo];
this.target = affects[spellNo];
}
public static Spell getSpell (String spellName, SpellType type, int level, byte[] buffer)
{
return new Spell (spellName, type, level, buffer);
}
public String getName ()
{
return name;
}
public SpellType getType ()
{
return spellType;
}
public int getLevel ()
{
return level;
}
public String getTranslation ()
{
return translation;
}
@Override
public String getText ()
{
return description;
}
public String getWhenCast ()
{
switch (whenCast)
{
case COMBAT:
return "Combat";
case LOOTING:
return "Looting";
case ANY_TIME:
return "Any time";
case CAMP:
return "Camp";
case COMBAT_OR_CAMP:
return "Combat or camp";
default:
return "?";
}
}
public String getArea ()
{
switch (target)
{
case PERSON:
return "1 Person";
case PARTY:
return "Entire party";
case MONSTER:
return "1 Monster";
case MONSTER_GROUP:
return "1 Monster group";
case ALL_MONSTERS:
return "All monsters";
case VARIABLE:
return "Variable";
case NONE:
return "None";
case CASTER:
return "Caster";
default:
return "?";
}
}
public String toHTMLTable ()
{
StringBuilder text = new StringBuilder ("<table border=\"1\"");
text.append (" width=\"100%\">\n");
text.append (" <tr>\n <td width=\"110\">Spell name</td>\n");
text.append (" <td>" + name + "</td>\n </tr>\n");
text.append (" <tr>\n <td>Translation</td>\n");
text.append (" <td>" + translation + "</td>\n </tr>\n");
text.append (" <tr>\n <td>Spell level</td>\n");
text.append (" <td>" + level + "</td>\n </tr>\n");
text.append (" <tr>\n <td>Spell type</td>\n");
text.append (" <td>" + getWhenCast () + "</td>\n </tr>\n");
text.append (" <tr>\n <td>Area of effect</td>\n");
text.append (" <td>" + getArea () + "</td>\n </tr>\n");
text.append (" <tr>\n <td>Description</td>\n");
text.append (" <td>" + getText () + "</td>\n </tr>\n");
text.append ("</table>");
return text.toString ();
}
@Override
public String toString ()
{
StringBuilder text = new StringBuilder (name);
while (text.length () < 14)
text.append (" ");
if (spellType == SpellType.PRIEST)
text.append ("P");
else
text.append ("M");
text.append (level);
while (text.length () < 20)
text.append (" ");
text.append (translation);
while (text.length () < 40)
text.append (" ");
text.append (getArea ());
while (text.length () < 60)
text.append (" ");
text.append (getWhenCast ());
return text.toString ();
}
private static String[] spellNames =
{ "KALKI", "DIOS", "BADIOS", "MILWA", "PORFIC", "MATU", "CALFO", "MANIFO", "MONTINO",
"LOMILWA", "DIALKO", "LATUMAPIC", "BAMATU", "DIAL", "BADIAL", "LATUMOFIS", "MAPORFIC",
"DIALMA", "BADIALMA", "LITOKAN", "KANDI", "DI", "BADI", "LORTO", "MADI", "MABADI",
"LOKTOFEIT", "MALIKTO", "KADORTO",
"HALITO", "MOGREF", "KATINO", "DUMAPIC", "DILTO", "SOPIC", "MAHALITO", "MOLITO",
"MORLIS", "DALTO", "LAHALITO", "MAMORLIS", "MAKANITO", "MADALTO", "LAKANITO", "ZILWAN",
"MASOPIC", "HAMAN", "MALOR", "MAHAMAN", "TILTOWAIT" };
private static String[] translations =
{ "Blessings", "Heal", "Harm", "Light", "Shield", "Blessing & zeal", "X-ray vision",
"Statue", "Still air", "More light", "Softness/supple", "Identification", "Prayer",
"Heal (more)", "Hurt (more)", "Cure poison", "Shield (big)", "Heal (greatly)",
"Hurt (greatly)", "Flame tower", "Location", "Life", "Death", "Blades", "Healing",
"Harm (incredibly)", "Recall", "The Word of Death", "Resurrection",
"Little Fire", "Body Iron", "Bad Air", "Clarity", "Darkness", "Glass", "Big fire",
"Spark storm", "Fear", "Blizzard blast", "Flame storm", "Terror", "Deadly air", "Frost",
"Suffocation", "Dispell", "Big glass", "Change", "Apport", "Great change",
"(untranslatable)" };
private static SpellThrown[] when =
{ SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.ANY_TIME,
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.LOOTING, SpellThrown.COMBAT,
SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.ANY_TIME, SpellThrown.COMBAT,
SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.ANY_TIME,
SpellThrown.ANY_TIME, SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT,
SpellThrown.CAMP, SpellThrown.CAMP, SpellThrown.COMBAT, SpellThrown.COMBAT,
SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
SpellThrown.ANY_TIME,
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.CAMP,
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT_OR_CAMP, SpellThrown.COMBAT,
SpellThrown.COMBAT, };
private static SpellTarget[] affects =
{ SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PARTY,
SpellTarget.CASTER, SpellTarget.PARTY, SpellTarget.CASTER, SpellTarget.MONSTER_GROUP,
SpellTarget.MONSTER_GROUP, SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.PARTY,
SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PERSON,
SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PARTY,
SpellTarget.PERSON, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.MONSTER_GROUP,
SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PARTY, SpellTarget.MONSTER_GROUP,
SpellTarget.PERSON,
SpellTarget.MONSTER, SpellTarget.CASTER, SpellTarget.MONSTER_GROUP, SpellTarget.NONE,
SpellTarget.MONSTER_GROUP, SpellTarget.CASTER, SpellTarget.MONSTER_GROUP,
SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP,
SpellTarget.MONSTER_GROUP, SpellTarget.ALL_MONSTERS, SpellTarget.ALL_MONSTERS,
SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER,
SpellTarget.PARTY, SpellTarget.VARIABLE, SpellTarget.PARTY, SpellTarget.PARTY,
SpellTarget.ALL_MONSTERS };
private static String[] descriptions =
{
"KALKI reduces the AC of all party members by one, and thus makes"
+ " them harder to hit.",
"DIOS restores from one to eight hit points of damage from a party"
+ "member. It will not bring dead back to life.",
"BADIOS causes one to eight hit points of damage to a monster, and"
+ " may kill it. It is the reverse of dios. Note the BA prefix which"
+ " means 'not'.",
"MILWA causes a softly glowing light to follow the party, allowing"
+ " them to see further into the maze, and also revealing all secret"
+ " doors. See also LOMILWA. This spell lasts only a short while.",
"PORFIC lowers the AC of the caster considerably. The effects last"
+ " for the duration of 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"
+ " on a chest 95% of the time.",
"MANIFO causes some of the monsters in a group to become stiff as"
+ " statues for one or more melee rounds. The chance of success,"
+ " and the duration of the effects, depend on the power of the"
+ " target monsters.",
"MONTINO causes the air around a group of monsters to stop"
+ " transmitting sound. Like MANIFO, only some of the monsters will"
+ " be affected, and for varying lengths of time. Monsters and"
+ " Party members under the influence of this spell cannot cast"
+ " spells, as they cannot utter the spell words!",
"LOMILWA is a MILWA spell with a much longer life span. Note that"
+ " when this spell, or MILWA are active, the Q option while"
+ " moving through the maze is active. If Q)UICK PLOTTING is on,"
+ " only the square you are in, and the next two squares, will"
+ " plot. Normally you might see five or six squares ahead with"
+ " LOMILWA on. Quick Plotting lets you move fast through known"
+ " areas. Note that it will be turned off when you enter camp or"
+ " combat mode.",
"DIALKO cures paralysis, and removes the effects of MANIFO and"
+ " KATINO from one member of the party.",
"LATUMAPIC makes it readily apparent exactly what the opposing" + " monsters really are.",
"BAMATU has the effects of MATU at twice the effectiveness.",
"DIAL restores two to 16 hit points of damage, and is similar to" + " DIOS.",
"BADIAL causes two to 16 hit points of damage in the same way as" + " BADIOS.",
"LATUMOFIS makes a poisoned person whole and fit again. Note that"
+ " poison causes a person to lose hit points steadily during"
+ " movement and combat.",
"MAPORFIC is an improved PORFIC, with effects that last for the" + " entire expedition.",
"DIALMA restores three to 24 hit points.",
"BADIALMA causes three to 24 hit points of damage.",
"LITOKAN causes a pillar of flame to strike a group of monsters,"
+ " doing three to 24 hits of damage to each. However, as with"
+ " many spells that affect entire groups, there is a chance that"
+ " individual monsters will be able to avoid or minimise its"
+ " effects. And some monsters will be resistant to it.",
"KANDI allows the user to locate characters in the maze. It tells on"
+ " which level, and in which rough area the dead one can be found.",
"DI causes a dead person to be resurrected. However, the renewed"
+ " character has but one hit point. Also, this spell is not as"
+ " effective or as safe as using the Temple.",
"BADI gives the affected monster a coronary attack. It may or may"
+ " not cause death to occur.",
"LORTO causes sharp blades to slice through a group, causing six to"
+ " 36 points of damage.",
"MADI causes all hit points to be restored and cures any condition" + " but death.",
"MABADI causes all but one to eight hit points to be removed from" + " the target.",
"LOKTOFEIT causes all party members to be teleported back to the"
+ " castle, minus all their equipment and most of their gold. There"
+ " is also a good chance this spell will not function.",
"MALIKTO causes 12 to 72 hit points of damage to all monsters. None"
+ " can escape or minimise its effects.",
"KADORTO restores the dead to life as does DI, but also restores all"
+ " hit points. However, it has the same drawbacks as the DI spell."
+ " KADORTO can be used to resurrect people even if they are ashes.",
"HALITO causes a flame ball the size of a baseball to hit a monster,"
+ " doing from one to eight points of damage.",
"MOGREF reduces the caster's AC by two. The effect lasts the entire" + " encounter.",
"KATINO causes most of the monsters in a group to fall asleep."
+ " Katino only effects normal, animal or humanoid monsters. The"
+ " chance of the spell affecting an individual monster, and the"
+ " duration of the effect, is inversely proportional to the power"
+ " of the monster. While asleep, monsters are easier to hit and"
+ " successful strikes do double damage.",
"DUMAPIC informs you of the party's exact displacement from the"
+ " stairs to the castle, vertically, and North and East, and also"
+ " tells you what direction you are facing.",
"DILTO causes one group of monsters to be enveloped in darkness,"
+ " which reduces their ability to defend against your attacks.",
"SOPIC causes the caster to become transparent. This means that"
+ " he is harder to see, and thus his AC is reduced by four.",
"MAHALITO causes a fiery explosion in a monster group, doing four"
+ " 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." };
package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.applefile.AbstractFile;
// -----------------------------------------------------------------------------------//
class Spell extends AbstractFile
// -----------------------------------------------------------------------------------//
{
private final SpellType spellType;
private SpellThrown whenCast;
private final int level;
private String translation;
private SpellTarget target;
private String description;
public enum SpellType
{
MAGE, PRIEST
};
public enum SpellTarget
{
PERSON, PARTY, MONSTER, MONSTER_GROUP, ALL_MONSTERS, VARIABLE, NONE, CASTER
};
public enum SpellThrown
{
COMBAT, ANY_TIME, LOOTING, CAMP, COMBAT_OR_CAMP
};
private static int lastSpellFound = -1;
// ---------------------------------------------------------------------------------//
private Spell (String spellName, SpellType type, int level, byte[] buffer)
// ---------------------------------------------------------------------------------//
{
super (spellName, buffer);
this.spellType = type;
this.level = level;
if (lastSpellFound + 1 < spellNames.length
&& spellName.equals (spellNames[lastSpellFound + 1]))
setSpell (++lastSpellFound);
else
{
for (int i = 0; i < spellNames.length; i++)
if (spellName.equals (spellNames[i]))
{
setSpell (i);
lastSpellFound = i;
break;
}
}
}
// ---------------------------------------------------------------------------------//
private void setSpell (int spellNo)
// ---------------------------------------------------------------------------------//
{
this.translation = translations[spellNo];
this.description = descriptions[spellNo];
this.whenCast = when[spellNo];
this.target = affects[spellNo];
}
// ---------------------------------------------------------------------------------//
public static Spell getSpell (String spellName, SpellType type, int level,
byte[] buffer)
// ---------------------------------------------------------------------------------//
{
return new Spell (spellName, type, level, buffer);
}
// ---------------------------------------------------------------------------------//
@Override
public String getName ()
// ---------------------------------------------------------------------------------//
{
return name;
}
// ---------------------------------------------------------------------------------//
public SpellType getType ()
// ---------------------------------------------------------------------------------//
{
return spellType;
}
// ---------------------------------------------------------------------------------//
public int getLevel ()
// ---------------------------------------------------------------------------------//
{
return level;
}
// ---------------------------------------------------------------------------------//
public String getTranslation ()
// ---------------------------------------------------------------------------------//
{
return translation;
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
return description;
}
// ---------------------------------------------------------------------------------//
public String getWhenCast ()
// ---------------------------------------------------------------------------------//
{
switch (whenCast)
{
case COMBAT:
return "Combat";
case LOOTING:
return "Looting";
case ANY_TIME:
return "Any time";
case CAMP:
return "Camp";
case COMBAT_OR_CAMP:
return "Combat or camp";
default:
return "?";
}
}
// ---------------------------------------------------------------------------------//
public String getArea ()
// ---------------------------------------------------------------------------------//
{
switch (target)
{
case PERSON:
return "1 Person";
case PARTY:
return "Entire party";
case MONSTER:
return "1 Monster";
case MONSTER_GROUP:
return "1 Monster group";
case ALL_MONSTERS:
return "All monsters";
case VARIABLE:
return "Variable";
case NONE:
return "None";
case CASTER:
return "Caster";
default:
return "?";
}
}
// ---------------------------------------------------------------------------------//
public String toHTMLTable ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ("<table border=\"1\"");
text.append (" width=\"100%\">\n");
text.append (" <tr>\n <td width=\"110\">Spell name</td>\n");
text.append (" <td>" + name + "</td>\n </tr>\n");
text.append (" <tr>\n <td>Translation</td>\n");
text.append (" <td>" + translation + "</td>\n </tr>\n");
text.append (" <tr>\n <td>Spell level</td>\n");
text.append (" <td>" + level + "</td>\n </tr>\n");
text.append (" <tr>\n <td>Spell type</td>\n");
text.append (" <td>" + getWhenCast () + "</td>\n </tr>\n");
text.append (" <tr>\n <td>Area of effect</td>\n");
text.append (" <td>" + getArea () + "</td>\n </tr>\n");
text.append (" <tr>\n <td>Description</td>\n");
text.append (" <td>" + getText () + "</td>\n </tr>\n");
text.append ("</table>");
return text.toString ();
}
// ---------------------------------------------------------------------------------//
@Override
public String toString ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder (name);
while (text.length () < 14)
text.append (" ");
if (spellType == SpellType.PRIEST)
text.append ("P");
else
text.append ("M");
text.append (level);
while (text.length () < 20)
text.append (" ");
text.append (translation);
while (text.length () < 40)
text.append (" ");
text.append (getArea ());
while (text.length () < 60)
text.append (" ");
text.append (getWhenCast ());
return text.toString ();
}
private static String[] spellNames =
{ "KALKI", "DIOS", "BADIOS", "MILWA", "PORFIC", "MATU", "CALFO", "MANIFO",
"MONTINO", "LOMILWA", "DIALKO", "LATUMAPIC", "BAMATU", "DIAL", "BADIAL",
"LATUMOFIS", "MAPORFIC", "DIALMA", "BADIALMA", "LITOKAN", "KANDI", "DI", "BADI",
"LORTO", "MADI", "MABADI", "LOKTOFEIT", "MALIKTO", "KADORTO",
"HALITO", "MOGREF", "KATINO", "DUMAPIC", "DILTO", "SOPIC", "MAHALITO", "MOLITO",
"MORLIS", "DALTO", "LAHALITO", "MAMORLIS", "MAKANITO", "MADALTO", "LAKANITO",
"ZILWAN", "MASOPIC", "HAMAN", "MALOR", "MAHAMAN", "TILTOWAIT" };
private static String[] translations =
{ "Blessings", "Heal", "Harm", "Light", "Shield", "Blessing & zeal", "X-ray vision",
"Statue", "Still air", "More light", "Softness/supple", "Identification",
"Prayer", "Heal (more)", "Hurt (more)", "Cure poison", "Shield (big)",
"Heal (greatly)", "Hurt (greatly)", "Flame tower", "Location", "Life", "Death",
"Blades", "Healing", "Harm (incredibly)", "Recall", "The Word of Death",
"Resurrection",
"Little Fire", "Body Iron", "Bad Air", "Clarity", "Darkness", "Glass", "Big fire",
"Spark storm", "Fear", "Blizzard blast", "Flame storm", "Terror", "Deadly air",
"Frost", "Suffocation", "Dispell", "Big glass", "Change", "Apport",
"Great change", "(untranslatable)" };
private static SpellThrown[] when =
{ SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.COMBAT,
SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.LOOTING,
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.ANY_TIME,
SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT,
SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.ANY_TIME,
SpellThrown.ANY_TIME, SpellThrown.ANY_TIME, SpellThrown.COMBAT,
SpellThrown.COMBAT, SpellThrown.CAMP, SpellThrown.CAMP, SpellThrown.COMBAT,
SpellThrown.COMBAT, SpellThrown.ANY_TIME, SpellThrown.COMBAT, SpellThrown.COMBAT,
SpellThrown.COMBAT, SpellThrown.ANY_TIME,
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.CAMP,
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT,
SpellThrown.COMBAT, SpellThrown.COMBAT, SpellThrown.COMBAT_OR_CAMP,
SpellThrown.COMBAT, SpellThrown.COMBAT, };
private static SpellTarget[] affects =
{ SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.MONSTER, SpellTarget.PARTY,
SpellTarget.CASTER, SpellTarget.PARTY, SpellTarget.CASTER,
SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.PARTY,
SpellTarget.PERSON, SpellTarget.PARTY, SpellTarget.PARTY, SpellTarget.PERSON,
SpellTarget.MONSTER, SpellTarget.PERSON, SpellTarget.PARTY, SpellTarget.PERSON,
SpellTarget.MONSTER, SpellTarget.PARTY, SpellTarget.PERSON, SpellTarget.PERSON,
SpellTarget.MONSTER, SpellTarget.MONSTER_GROUP, SpellTarget.PERSON,
SpellTarget.MONSTER, SpellTarget.PARTY, SpellTarget.MONSTER_GROUP,
SpellTarget.PERSON,
SpellTarget.MONSTER, SpellTarget.CASTER, SpellTarget.MONSTER_GROUP,
SpellTarget.NONE, SpellTarget.MONSTER_GROUP, SpellTarget.CASTER,
SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP,
SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP, SpellTarget.ALL_MONSTERS,
SpellTarget.ALL_MONSTERS, SpellTarget.MONSTER_GROUP, SpellTarget.MONSTER_GROUP,
SpellTarget.MONSTER, SpellTarget.PARTY, SpellTarget.VARIABLE, SpellTarget.PARTY,
SpellTarget.PARTY, SpellTarget.ALL_MONSTERS };
private static String[] descriptions =
{ "KALKI reduces the AC of all party members by one, and thus makes"
+ " them harder to hit.",
"DIOS restores from one to eight hit points of damage from a party"
+ "member. It will not bring dead back to life.",
"BADIOS causes one to eight hit points of damage to a monster, and"
+ " may kill it. It is the reverse of dios. Note the BA prefix which"
+ " means 'not'.",
"MILWA causes a softly glowing light to follow the party, allowing"
+ " them to see further into the maze, and also revealing all secret"
+ " doors. See also LOMILWA. This spell lasts only a short while.",
"PORFIC lowers the AC of the caster considerably. The effects last"
+ " for the duration of 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"
+ " on a chest 95% of the time.",
"MANIFO causes some of the monsters in a group to become stiff as"
+ " statues for one or more melee rounds. The chance of success,"
+ " and the duration of the effects, depend on the power of the"
+ " target monsters.",
"MONTINO causes the air around a group of monsters to stop"
+ " transmitting sound. Like MANIFO, only some of the monsters will"
+ " be affected, and for varying lengths of time. Monsters and"
+ " Party members under the influence of this spell cannot cast"
+ " spells, as they cannot utter the spell words!",
"LOMILWA is a MILWA spell with a much longer life span. Note that"
+ " when this spell, or MILWA are active, the Q option while"
+ " moving through the maze is active. If Q)UICK PLOTTING is on,"
+ " only the square you are in, and the next two squares, will"
+ " plot. Normally you might see five or six squares ahead with"
+ " LOMILWA on. Quick Plotting lets you move fast through known"
+ " areas. Note that it will be turned off when you enter camp or"
+ " combat mode.",
"DIALKO cures paralysis, and removes the effects of MANIFO and"
+ " KATINO from one member of the party.",
"LATUMAPIC makes it readily apparent exactly what the opposing"
+ " monsters really are.",
"BAMATU has the effects of MATU at twice the effectiveness.",
"DIAL restores two to 16 hit points of damage, and is similar to" + " DIOS.",
"BADIAL causes two to 16 hit points of damage in the same way as" + " BADIOS.",
"LATUMOFIS makes a poisoned person whole and fit again. Note that"
+ " poison causes a person to lose hit points steadily during"
+ " movement and combat.",
"MAPORFIC is an improved PORFIC, with effects that last for the"
+ " entire expedition.",
"DIALMA restores three to 24 hit points.",
"BADIALMA causes three to 24 hit points of damage.",
"LITOKAN causes a pillar of flame to strike a group of monsters,"
+ " doing three to 24 hits of damage to each. However, as with"
+ " many spells that affect entire groups, there is a chance that"
+ " individual monsters will be able to avoid or minimise its"
+ " effects. And some monsters will be resistant to it.",
"KANDI allows the user to locate characters in the maze. It tells on"
+ " which level, and in which rough area the dead one can be found.",
"DI causes a dead person to be resurrected. However, the renewed"
+ " character has but one hit point. Also, this spell is not as"
+ " effective or as safe as using the Temple.",
"BADI gives the affected monster a coronary attack. It may or may"
+ " not cause death to occur.",
"LORTO causes sharp blades to slice through a group, causing six to"
+ " 36 points of damage.",
"MADI causes all hit points to be restored and cures any condition"
+ " but death.",
"MABADI causes all but one to eight hit points to be removed from"
+ " the target.",
"LOKTOFEIT causes all party members to be teleported back to the"
+ " castle, minus all their equipment and most of their gold. There"
+ " is also a good chance this spell will not function.",
"MALIKTO causes 12 to 72 hit points of damage to all monsters. None"
+ " can escape or minimise its effects.",
"KADORTO restores the dead to life as does DI, but also restores all"
+ " hit points. However, it has the same drawbacks as the DI spell."
+ " KADORTO can be used to resurrect people even if they are ashes.",
"HALITO causes a flame ball the size of a baseball to hit a monster,"
+ " doing from one to eight points of damage.",
"MOGREF reduces the caster's AC by two. The effect lasts the entire"
+ " encounter.",
"KATINO causes most of the monsters in a group to fall asleep."
+ " Katino only effects normal, animal or humanoid monsters. The"
+ " chance of the spell affecting an individual monster, and the"
+ " duration of the effect, is inversely proportional to the power"
+ " of the monster. While asleep, monsters are easier to hit and"
+ " successful strikes do double damage.",
"DUMAPIC informs you of the party's exact displacement from the"
+ " stairs to the castle, vertically, and North and East, and also"
+ " tells you what direction you are facing.",
"DILTO causes one group of monsters to be enveloped in darkness,"
+ " which reduces their ability to defend against your attacks.",
"SOPIC causes the caster to become transparent. This means that"
+ " he is harder to see, and thus his AC is reduced by four.",
"MAHALITO causes a fiery explosion in a monster group, doing four"
+ " 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.DataBuffer;
// -----------------------------------------------------------------------------------//
public class Wiz4Image extends AbstractImage
// -----------------------------------------------------------------------------------//
{
// ---------------------------------------------------------------------------------//
public Wiz4Image (String name, byte[] buffer, int rows, int cols) // 5, 6
// ---------------------------------------------------------------------------------//
{
super (name, buffer);

View File

@ -6,12 +6,16 @@ import java.util.List;
import com.bytezone.diskbrowser.applefile.AbstractFile;
import com.bytezone.diskbrowser.utilities.HexFormatter;
// -----------------------------------------------------------------------------------//
public class Wiz4Monsters extends AbstractFile
// -----------------------------------------------------------------------------------//
{
final List<Wiz4Image> images = new ArrayList<> ();
final List<Integer> blocks = new ArrayList<> ();
// ---------------------------------------------------------------------------------//
public Wiz4Monsters (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
@ -30,8 +34,10 @@ public class Wiz4Monsters extends AbstractFile
}
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
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.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 final List<Monster> monsters = new ArrayList<> ();
public Wiz5Monsters (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
Wiz5Monsters (String name, byte[] buffer)
// ---------------------------------------------------------------------------------//
{
super (name, buffer);
@ -56,14 +60,18 @@ public class Wiz5Monsters extends AbstractFile implements Iterable<Wiz5Monsters.
}
}
// ---------------------------------------------------------------------------------//
@Override
public Iterator<Monster> iterator ()
// ---------------------------------------------------------------------------------//
{
return monsters.iterator ();
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
StringBuilder text = new StringBuilder ();
@ -90,7 +98,9 @@ public class Wiz5Monsters extends AbstractFile implements Iterable<Wiz5Monsters.
return text.toString ();
}
// ---------------------------------------------------------------------------------//
class Monster
// ---------------------------------------------------------------------------------//
{
private final int id;
private final List<DataBuffer> dataBuffers = new ArrayList<> ();
@ -151,7 +161,9 @@ public class Wiz5Monsters extends AbstractFile implements Iterable<Wiz5Monsters.
}
}
// ---------------------------------------------------------------------------------//
class DataBuffer
// ---------------------------------------------------------------------------------//
{
private final int block;
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.wizardry.Header.ScenarioData;
// -----------------------------------------------------------------------------------//
public class Wizardry4BootDisk extends PascalDisk
// -----------------------------------------------------------------------------------//
{
public Header scenarioHeader;
// private final List<AppleDisk> disks = new ArrayList<> ();
@ -26,7 +28,9 @@ public class Wizardry4BootDisk extends PascalDisk
private Huffman huffman;
private final int version;
// ---------------------------------------------------------------------------------//
public Wizardry4BootDisk (AppleDisk[] dataDisks)
// ---------------------------------------------------------------------------------//
{
super (dataDisks[0]);
@ -133,8 +137,10 @@ public class Wizardry4BootDisk extends PascalDisk
}
}
// ---------------------------------------------------------------------------------//
private void linkMonsterImages4 (DefaultMutableTreeNode monstersNode,
FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{
List<DiskAddress> pictureBlocks = fileEntry.getSectors ();
@ -151,8 +157,10 @@ public class Wizardry4BootDisk extends PascalDisk
}
}
// ---------------------------------------------------------------------------------//
private void linkMonsterImages5 (DefaultMutableTreeNode monstersNode,
FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{
List<DiskAddress> pictureBlocks = fileEntry.getSectors ();
@ -169,7 +177,9 @@ public class Wizardry4BootDisk extends PascalDisk
}
}
// ---------------------------------------------------------------------------------//
private void linkMazeLevels4 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{
ScenarioData mazeData = scenarioHeader.data.get (Header.MAZE_AREA);
@ -191,7 +201,9 @@ public class Wizardry4BootDisk extends PascalDisk
}
}
// ---------------------------------------------------------------------------------//
private void linkMazeLevels5 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{
byte[] buffer = fileEntry.getDataSource ().buffer;
List<DiskAddress> blocks = fileEntry.getSectors ();
@ -221,7 +233,9 @@ public class Wizardry4BootDisk extends PascalDisk
afs.setSectors (allMazeBlocks);
}
// ---------------------------------------------------------------------------------//
private void linkBlock1 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{
byte[] buffer = fileEntry.getDataSource ().buffer;
List<DiskAddress> blocks = fileEntry.getSectors ();
@ -248,7 +262,9 @@ public class Wizardry4BootDisk extends PascalDisk
afs.setSectors (allBlocks);
}
// ---------------------------------------------------------------------------------//
private void linkBlock2 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{
byte[] buffer = fileEntry.getDataSource ().buffer;
List<DiskAddress> blocks = fileEntry.getSectors ();
@ -275,7 +291,9 @@ public class Wizardry4BootDisk extends PascalDisk
afs.setSectors (allBlocks);
}
// ---------------------------------------------------------------------------------//
private void linkOracle (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{
byte[] buffer = fileEntry.getDataSource ().buffer;
List<DiskAddress> blocks = fileEntry.getSectors ();
@ -309,8 +327,10 @@ public class Wizardry4BootDisk extends PascalDisk
afs.setSectors (allOracleBlocks);
}
// ---------------------------------------------------------------------------------//
private void addToNode (AbstractFile af, DefaultMutableTreeNode node,
List<DiskAddress> blocks)
// ---------------------------------------------------------------------------------//
{
DefaultAppleFileSource dafs =
new DefaultAppleFileSource (af.getName (), af, this, blocks);
@ -319,8 +339,10 @@ public class Wizardry4BootDisk extends PascalDisk
node.add (childNode);
}
// ---------------------------------------------------------------------------------//
private DefaultMutableTreeNode linkNode (String name, String text,
DefaultMutableTreeNode parent)
// ---------------------------------------------------------------------------------//
{
DefaultAppleFileSource afs = new DefaultAppleFileSource (name, text, this);
DefaultMutableTreeNode node = new DefaultMutableTreeNode (afs);
@ -328,7 +350,9 @@ public class Wizardry4BootDisk extends PascalDisk
return node;
}
// ---------------------------------------------------------------------------------//
public static boolean isWizardryIVorV (Disk disk, boolean debug)
// ---------------------------------------------------------------------------------//
{
// Wizardry IV or V boot code
byte[] header = { 0x00, (byte) 0xEA, (byte) 0xA9, 0x60, (byte) 0x8D, 0x01, 0x08 };

File diff suppressed because it is too large Load Diff