Wizardry Proving Grounds v3.2 - Pascal Code Changes =================================================== Author: Eric Labelle (email:snafaru@zimlab.com) Release date of this document: 18 March 2026 Note: These are the code fixes and enhancements. The database fixes are also included in the release. Web Site: https://www.zimlab.com/wizardry/proving-grounds-v3 GitHub: https://github.com/snafaru The baseline is the re-engineered Pascal source code (and assembler code) from the Wizardry_I program by Thomas William Ewers. This project would not exist without it. Final compiled file names: STARTUP.CODE WIZARDRY.CODE Location: Boot and scenario disks. Summary of fixes, game enhancements, and quality of life improvments: Boot Side: SYSTEM.STARTUP Bug/Issue #: ST001 - Version and Date Bug/Issue #: ST002 - Bypass Copy Protection Check Bug/Issue #: ST003 - Boot Disk Write Protection Check Bug/Issue #: ST004 - 80-Column IIe Scenario and Boot Sides: WIZARDRY.CODE Bug/Issue #: WC001 - Bishop Bug Bug/Issue #: WC002 - Misspelling Dispel, Morgue and Group # Bug/Issue #: WC003 - Latumapic does not work Bug/Issue #: WC004 - Misspelling of Gilgamesh Bug/Issue #: WC005 - No Friends Fix (a.k.a. monster resists befriending) Bug/Issue #: WC006 - Haman Mahaman Bug/Issue #: WC007 - Object Special Number 23 Bug/Issue #: WC008 - Hidden CTRL-G Bell Bug/Issue #: WC009 - Montino Bug/Issue #: WC010 - Regeneration Degeneration Bug/Issue #: WC011 - Monster Affliction Dispel Bug/Issue #: WC012 - Mamorlis Bug/Issue #: WC013 - Mabadi Bug/Issue #: WC014 - Manifo Bug/Issue #: WC015 - To Hit Bug/Issue #: WC016 - Luck (LUCKSKIL) Bug/Issue #: WC017 - Camp Use Item Screen Update Enhancement #: WC018 - Display Hit Probability Enhancement #: WC019 - Remove Password Prompts Enhancement #: WC020 - Show Spells During Combat Bug/Issue #: WC021 - Monsters Wrongly Casting Zilwan Bug/Issue #: WC022 - Treasure Tables Range Bug Enhancement #: WC023 - Surprise Round Enhancement Release #: WC024 - Interim Release 09 Feb 2023 (Includes a Treasure Table fix) Bug/Issue #: WC025 - Fix Addlongs vs Experience Points Bug/Issue #: WC026 - Misspelling Bad Amount Enhancement #: WC027 - Drain Only Once Per Combat Enhancement Enhancement #: WC028 - Loktofeit Release #: WC029 - Interim Release 14 Feb 2023 (Includes fixed spelling) Enhancement #: WC030 - Ninja Enhancements Bug/Issue #: WC031 - Mapiro Mahama Diromat Bug/Issue #: WC032 - Roster Out Characters Bug/Issue #: WC033 - Inventory Full Fix Bug/Issue #: WC034 - Search for Item Release #: WC035 - Release 2023-03-17 and fixed a misspelling Release #: WC036 - Release 2023-03-23 - In alignment with a ProDOS release and added Quit the game Bug/Issue #: WC037 - Disarm Trap Bug Enhancement #: WC038 - Camp Screen Update Release #: WC039 - Release 09 Apr 2023 - Fix Maze Text Entry Overflow Crash Release #: WC040 - Release 03 Aug 2023 - Pool and Divide Gold and More Enhancement #: WC041 - Do not transfer quest items - Show full 4-digits year on splash screen Release #: WC042 - Release 08 Feb 2024 - Allow transfer characters to any scenario copy - Correct spelling Enhancement #: WC043 - Kandi spell enhancements - Precise location of dead characters and added for D)isbanded parties as well Enhancement #: WC044 - Display Silenced Character in the Status Window Enhancement #: WC045 - Auto Update Hit Points of Poisoned Characters in the Status Window Enhancement #: WC046 - Monsters cannot yell for help when surprised Release #: WC047 - Release 24 March 2024 v3.1 Enhancement #: WC048 - Quickplot To Stop Update Hit Points of Poisoned Characters Enhancement #: WC049 - New Fonts Enhancement #: WC050 - Chute Pause Bug/Issue #: WC051 - Fizzle Fix Release #: WC052 - Release 14 Feb 2026 v3.1.1 - Last-Before-RNG-Fix Bug/Issue #: WC053 - Random Number Generator Fix Release #: WC054 - Release 18 Mar 2026 v3.2 Bug/Issue #: ST001 - Version and Date ======================================== Status: Fixed. Recompiled. Verified. Date of change: 26-Dec-2022 Contributor: E. Labelle The Issue: To track which version and release date we are at. The Fix: Change the version and date text displayed as needed. Source Disk: Wiz1E.dsk File: OPTIONS.TEXT Segment: PROCEDURE OPTIONS; (* P070301 *) Code From: WRITE( ' VERSION 2.1 OF 22-JAN-82 SER:'); Code To: New text output on boot splash screen. (* ST001 CHANGE VERSION AND DATE DISPLAY AS NEEDED *) WRITE( ' VERSION 3.0 OF 26-DEC-22 SER:'); Final Compiled File Name: SYSTEM.STARTUP Destination Disk: Any Wizardry Proving Grounds boot disk. Bug/Issue #: ST002 - Bypass Copy Protection Check ==================================================== Status: Fixed. Recompiled. Verified. Date of change: 25-Dec-2022 Contributor: E. Labelle (Information source: Thomas W. Ewers) The Issue: After putting a new compiled version of SYSTEM.STARTUP (STARTUP.CODE) on a Wizardry boot disk, the latter will hang on boot. This is due to the copy protection scheme used. Note: Skipping the write-protect check has not been implemented yet, therefore do not forget to write-protect your boot disk, else it will hang. The Fix: Remark out the copy protection check to bypass it. Source Disk: Wiz1E.dsk File: STARTUP.TEXT Segment: PROCEDURE CHKCOPY; (* P07004 *) Code From: IF GOODCOPY THEN *) Code To: Putting the code between "(* " and " *)" makes it a remark and thus it is skipped, therefore bypassing the copy protection check. (* ST001 REMARK OUT/BYPASS COPY PROTECTION CHECK *) (* IF GOODCOPY THEN *) Final Compiled File Name: SYSTEM.STARTUP Destination Disk: Any Wizardry Proving Grounds boot disk. Bug/Issue #: ST003 - Boot Disk Write Protection Check ======================================================== Status: Fixed. Recompiled. Verified. Date of change: 25-Dec-2022 Contributor: E. Labelle (Information source: Thomas W. Ewers, Chris Torrence) The Issue: If the write-protection tab on a physical diskette, or the read-only flag on a diskette image, is not on then game will go to a blank screen and stay in an infinity loop right after the game boot splash screens. The Fix: Remark out the write protection check code to bypass it. Source Disk: Wiz1E.dsk File: OPTIONS.TEXT Segment: PROCEDURE OPTIONS; (* P070301 *) Code From: UNITREAD( DRIVE1, IOBUFF, SIZEOF( IOBUFF), 0, 0); UNITWRITE( DRIVE1, IOBUFF, SIZEOF( IOBUFF), 0, 0); IF IORESULT <> 16 THEN REPEAT UNTIL FALSE; Code To: Putting the code between "(* " and " *)" makes it a remark and thus it is skipped, therefore bypassing the write protection check. (* ST003 REMARK OUT/BYPASS BOOT DISK WRITE-PROTECT CHECK *) (* UNITREAD( DRIVE1, IOBUFF, SIZEOF( IOBUFF), 0, 0); UNITWRITE( DRIVE1, IOBUFF, SIZEOF( IOBUFF), 0, 0); IF IORESULT <> 16 THEN REPEAT UNTIL FALSE; *) Final Compiled File Name: SYSTEM.STARTUP Destination Disk: Any Wizardry Proving Grounds boot disk. Bug/Issue #: ST004 - 80-Column IIe ====================================== Status: Fixed. Verified. Date of change: 04-Jan-2023 Contributor: E. Labelle (Information source: Chris Torrence). References: https://archive.org/details/WizardryProvingGrounds https://www.youtube.com/watch?v=6v35XbbBKQw&t=360s The Issue: A bug where on an Apple //e (or //e emulator) with an 80-column card in the aux slot, Wizardry would incorrectly switch to 80-column mode and have weird spacing between all characters and lines on the screen. To fix this, memory location $B91D was changed from a JMP instruction ($6C) to a RTS ($60). This prevents Wizardry from attempting to switch out of 80-column mode, which was actually causing it to switch into 80 columns on an Apple //e. The Fix: Hex edit the value 6C to 60. Update the release date. Why this fix: To have Wizardry running in 40-column text mode on an Apple //e or emulator. Sector editing is the only way to accomplish this for now until someone comes up with a better solution. Sector Editing: Start your favorite sector editor Insert the Wizardry Boot disk Search for Hex 6C F6 00 Replace Hex 6C to 60 Note: This can be reversed if you wish or as needed. Destination Disk: Any Wizardry Proving Grounds boot disk. Bug/Issue #: WC001 - Bishop Bug ================================== Status: Fixed. Recompiled. Verified. Date of change: 19-Dec-2022 Contributor: E. Labelle (Information source: R. Woodhead) The Issue: If your character is a Bishop, it can identify the true name of an item. These items are in its inventory slots 1 through 8. Pressing other keys besides 1 through 8 can have the following benefits: - 9 : The Bishop gains 100 million experience points. - S : The character below the Bishop gains 100 million experience points. - J : The character below the Bishop gains 100 million gold pieces. The fix: This bug is due to a programming error. The code is similar to "IF (CH>="1") OR (CH<="8") THEN". The "OR" should have been a "AND". Why this fix: To prevent exploit and to prevent game corruption if other keys are pressed. Source Disk: Wiz1C.dsk File: UTILITIE.TEXT Segment: PROCEDURE IDITEM; (* P010108 *) Code From: UNTIL (ITEMX > 0) OR (ITEMX <= CHARACTR[ CHARX].POSS.POSSCNT); Code To: (* WC001 CHANGE -OR- TO -AND- SO KEYS OUTSIDE 1-8 CANNOT BE USED *) UNTIL (ITEMX > 0) AND (ITEMX <= CHARACTR[ CHARX].POSS.POSSCNT); Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC002 - Misspelling Dispel, Morgue and Group # ============================================================== Status: Fixed. Recompiled. Verified. Date of change: 26-Dec-2022 Contributor: E. Labelle (Information source: D. Molony, E. Labelle) The Issue: Misspelling Dispel and Morgue. Also fixing spelling of "GROUP # ?" for consistency. - While in the maze, you can cast the Kandi spell to find where a character is. If the character you are looking for is dead but has been brought back to the castle, you get the following message - "The soul of Werdna is.. in the mourge". Corrected "mourge" to "morgue". - The word "Dispel" was misspelled "Dispell" throughout the game, they are corrected here: Old Spelling New Spelling D)ISPELL D)ISPEL DISPELL WHICH GROUP# ? DISPEL WHICH GROUP # ? DISPELLS! DISPELS! The fix: Edit the text. Why this fix: To correct misspelling and consistency in display. Source Disk: Wiz1C.dsk File: UTILITIE.TEXT Segment: PROCEDURE KANDILOC; (* P01010C *) Code From: WRITELN( 'IN THE MOURGE') Code To: (* WC002 CHANGE -MOURGE- TO -MORGUE- *) WRITELN( 'IN THE MORGUE') Source Disk: Wiz1B.dsk File: COMBAT2.TEXT Segment: PROCEDURE SPGROUP( SPELLI: INTEGER; (* P010610 *) Code From: WHICHGRP( 'CAST SPELL ON GROUP #?', SPELLCST) Code To: (* WC002 CHANGE -GROUP #?- TO -GROUP # ?- *) WHICHGRP( 'CAST SPELL ON GROUP # ?', SPELLCST) Source Disk: Wiz1B.dsk File: COMBAT2.TEXT Segment: BEGIN (* CACTION *) Code From: BEGIN BDISPELL := TRUE; PRINTSTR( 'D)ISPELL ') END; . . . 'D': IF BDISPELL THEN WHICHGRP( 'DISPELL WHICH GROUP# ?', -5); 'R': RUNAWAY; 'F': IF MYCHARX < 3 THEN WHICHGRP( 'FIGHT AGAINST GROUP# ?', -1); Code To: BEGIN BDISPELL := TRUE; (* WC002 CHANGE -'D)ISPELL '- TO -'D)ISPEL '- *) PRINTSTR( 'D)ISPEL ') END; . . . 'D': IF BDISPELL THEN (* WC002 CHANGE -DISPELL WHICH GROUP# ?- *) (* TO -DISPEL WHICH GROUP # ?- *) WHICHGRP( 'DISPEL WHICH GROUP # ?', -5); 'R': RUNAWAY; 'F': IF MYCHARX < 3 THEN (* WC002 CHANGE -GROUP# ?- TO -GROUP # ?- *) WHICHGRP( 'FIGHT AGAINST GROUP # ?', -1); Source Disk: Wiz1B.dsk File: COMBAT5.TEXT Segment: PROCEDURE DODISPEL; (* P010913 *) Code From: PRINTSTR( 'DISPELLS!'); Code To: (* WC002 CHANGE -DISPELLS!- TO -DISPELS!- *) PRINTSTR( 'DISPELS!'); Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC003 - Latumapic does not work =============================================== Status: Fixed. Recompiled. Verified. Date of change: 27-Dec-2022 Contributor: E. Labelle (Information source: DDG Ahab) The Issue: Casting the Latumapic spell does not identify the monsters' true names, thus making this spell useless. The fix: Change the loop variable from LLBASE04 to GROUPI. Why this fix: To make the Latumapic spell work on on all groups of monsters. Source Disk: Wiz1B.dsk File: COMBAT4.TEXT Segment: PROCEDURE DOPRIEST; (* P01081B *) Code From: IF SPELL = LATUMAPI THEN BEGIN FOR GROUPI := 1 TO 4 DO BATTLERC[ LLBASE04].A.IDENTIFI := TRUE; (* BUG? WITH BASE04*) END; Code To: IF SPELL = LATUMAPI THEN BEGIN FOR GROUPI := 1 TO 4 DO (* WC003 FROM -BATTLERC[ LLBASE04]- TO -BATTLERC[ GROUPI]- *) BATTLERC[ GROUPI].A.IDENTIFI := TRUE; (* BUG? WITH BASE04 *) END; Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC004 - Misspelling of Gilgamesh ================================================ Status: Fixed. Recompiled. Verified. Date of change: 28-Dec-2022 Contributor: E. Labelle (Information source: E. Labelle) The Issue: At the Castle Market, the option to go to G)ilgamesh's Tavern missed it possessive "s". The fix: Added trailing "s" in "Gilgamesh's". Why this fix: In accordance to standard English rules. Matches how it is spelled everywhere else. Source Disk: Wiz1C.dsk File: CASTLE2.TEXT Segment: PROCEDURE P010A26; (* P010A26 *) Code From: BEGIN GOTOXY( 0, 13); WRITE( CHR( 11)); WRITE( ' ' : 13); WRITELN( 'YOU MAY GO TO:'); WRITELN; WRITELN( 'THE A)DVENTURER''S INN, G)ILGAMESH'''); WRITELN( 'TAVERN, B)OLTAC''S TRADING POST, THE'); WRITELN( 'TEMPLE OF C)ANT, OR THE E)DGE OF TOWN.') END; Code To: BEGIN GOTOXY( 0, 13); WRITE( CHR( 11)); WRITE( ' ' : 13); WRITELN( 'YOU MAY GO TO:'); WRITELN; (* WC004 CHANGE -G)ILGAMESH''');- TO -G)ILGAMESH''S');- *) WRITELN( 'THE A)DVENTURER''S INN, G)ILGAMESH''S'); WRITELN( 'TAVERN, B)OLTAC''S TRADING POST, THE'); WRITELN( 'TEMPLE OF C)ANT, OR THE E)DGE OF TOWN.') END; Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC005 - No Friends Fix ====================================== Status: Fixed. Recompiled. Verified. Date of change: 30-Dec-2022 Contributor: E. Labelle (Information source: E. Labelle) The Issue: The monsters' friends/no friends attribute does not work at all. In a monster record, there is an attribute to resist befriending, meaning you cannot have a friendly encounter with them if set to on (or true). The issue was that even if that attribute was on, you could still have a friendly encounter with them. The fix: Added a a line of code to the FRIENDLY procedure to check if that monster's attribute is on for the first group of monsters, and if it is then exit the FRIENDLY procedure. Why this fix: To make the monster's resistance to befriending work. Source Disk: Wiz1B.dsk File: COMBAT.TEXT Segment: PROCEDURE FRIENDLY; (* P010509 *) Code From: BEGIN (* FRIENDLY *) GOODLEAV := FALSE; Code To: Note that BATTLERC is the monster group where 1 means the first monster group, WEPVSTY3 is the monster resistance where 0 is No Friends, 1 is Fire, 2 is Cold, Etc. BEGIN (* FRIENDLY *) (* WC005 EXIT IF FIRST MONSTER GROUP RESISTS BEFRIENDING *) IF BATTLERC[ 1].B.WEPVSTY3[ 0] THEN EXIT (FRIENDLY); GOODLEAV := FALSE; Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC006 - Haman Mahaman ===================================== Status: Fixed. Recompiled. Verified. Date of change: 01-Jan-2023 Contributor: E. Labelle (Information source: Thomas W. Ewers) The Bug: There are supposed to be seven possible effects, with less powerful ones more likely to be selected. Instead, each spell has three possible effects with equal distribution, and two of the effects are impossible. The fix: Added parenthesis and changed the Mahaman flag value from 7 to 8. Why this fix: To make Haman and Mahaman work as intended. Source Disk: Wiz1B.dsk File: COMBAT4.TEXT Segment: PROCEDURE HAMMAHAM( MAHAMFLG: INTEGER); (* P01080E *) and PROCEDURE DOMAGE; (* P01081C *) Code From: BEGIN (* HAMMAHAM *) IF MAHAMFLG = 7 THEN PRINTSTR( 'MA'); PRINTSTR( 'HAMAN IS INTONED AND...'); PAUSE2; MVCURSOR( 1, 13); IF CHARACTR[ BATI].CHARLEV < 13 THEN BEGIN PRINTSTR( 'FAILS!'); EXIT( HAMMAHAM) END; CHARACTR[ BATI].CHARLEV := CHARACTR[ BATI].CHARLEV - 1; DRAINED[ BATI] := TRUE; CASE RANDOM MOD 3 * MAHAMFLG OF (* MAHAMFLG IS 6 OR 7 *) 0, 1, 2, 3, 4, 5: HAMCURE; (* 1? 2? 3? 4? 5? *) 7, 8, 9, 10, 11: HAMSILEN; (* 8? 9? 10? 11? *) 12, 13, 22, 23: HAMMAGIC; (* 13?, 22?, 23? *) 14, 20, 21: HAMTELEP; (* 14?, 20? *) 6, 15, 19: HAMHEAL; (* 15?, 19? *) 17: HAMPROT; (* 17? DEAD CODE *) 16, 18: HAMALIVE; (* 16?, 18? DEAD CODE *) (* MAYBE THEY WANTED "RANDOM MOD (3 * MAHAMFLG)", AND MAHAMFLG = 6 OR 8 DEPENDING ON SPELL *) END; Code To: BEGIN (* HAMMAHAM *) (* WC006 FROM -MAHAMFLG = 7- TO -MAHAMFLG = 8 *) IF MAHAMFLG = 8 THEN PRINTSTR( 'MA'); PRINTSTR( 'HAMAN IS INTONED AND...'); PAUSE2; MVCURSOR( 1, 13); IF CHARACTR[ BATI].CHARLEV < 13 THEN BEGIN PRINTSTR( 'FAILS!'); EXIT( HAMMAHAM) END; CHARACTR[ BATI].CHARLEV := CHARACTR[ BATI].CHARLEV - 1; DRAINED[ BATI] := TRUE; (* WC006 FROM -3 * MAHAMFLG- TO -(3 * MAHAMFLG)- *) CASE RANDOM MOD (3 * MAHAMFLG) OF (* MAHAMFLG IS 6 OR 8 *) 0, 1, 2, 3, 4, 5: HAMCURE; 7, 8, 9, 10, 11: HAMSILEN; 12, 13, 22, 23: HAMMAGIC; 14, 20, 21: HAMTELEP; 6, 15, 19: HAMHEAL; 17: HAMPROT; 16, 18: HAMALIVE; END; Code From: IF SPELL = MAHAMAN THEN HAMMAHAM( 7); Code To: IF SPELL = MAHAMAN THEN (* WC006 CHANGE -HAMMAHAM( 7)- TO -HAMMAHAM( 8)- *) HAMMAHAM( 8); Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC007 - Object Special Number 23 ================================================ Status: Fixed. Recompiled. Verified. Date of change: 02-Jan-2023 Contributor: E. Labelle (Information source: Thomas W. Ewers) The Bug: Error in code. The fix: Added "- 1" to the code so that the routine applies the effect to characters 1 through 6 instead of 1 through 7. Why this fix: To have the correct code. Source Disk: Wiz1B.dsk File: UTILITIE2.TEXT Segment: PROCEDURE CHSPCPOW; (* P01011A *) Code From: 23: BEGIN (* LOOKS LIKE BUG! PARTYCNT - 1 !!! *) FOR SPCTEMP := 0 TO PARTYCNT DO CHARACTR[ SPCTEMP].HPLEFT := CHARACTR[ SPCTEMP].HPMAX END; Code To: 23: BEGIN (* WC007 FROM -PARTYCNT- TO -PARTYCNT - 1- *) FOR SPCTEMP := 0 TO PARTYCNT - 1 DO CHARACTR[ SPCTEMP].HPLEFT := CHARACTR[ SPCTEMP].HPMAX END; Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC008 - Hidden CTRL-G Bell ========================================== Status: Fixed. Recompiled. Verified. Date of change: 03-Jan-2023 Contributor: E. Labelle (Information source: Thomas W. Ewers) The Issue: The COMBAT5.TEXT contains three hidden CTRL-G ascii characters to ring the BELL 3 times for when your character scores a critical hit. Key word here: hidden. The fix: Replace the three hidden CTRL-G by three CHR(7). Why this fix: To avoid future problems when editing or viewing COMBAT5.TEXT. To make it clear what is going on in the code. Source Disk: Wiz1B.dsk File: COMBAT5.TEXT Segment: PROCEDURE DAM2ENMY; (* P01090F *) Code From: BEGIN MVCURSOR( 1, 14); PRINTSTR( 'A CRITICAL HIT!'); WRITE( ' '); BATTLERC[ VICTIM].A.TEMP04[ SINGLEX].HPLEFT := 0; PAUSE1; CLRRECT( 1, 14, 38, 1) END; Code To: BEGIN MVCURSOR( 1, 14); PRINTSTR( 'A CRITICAL HIT!'); (* WC008 REPLACE THREE HIDDEN CTRL-G BY CHR( 7) *) WRITE( CHR( 7), CHR( 7), CHR( 7)); BATTLERC[ VICTIM].A.TEMP04[ SINGLEX].HPLEFT := 0; PAUSE1; CLRRECT( 1, 14, 38, 1) END; Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC009 - Montino =============================== Status: Fixed. Recompiled. Verified. Date of change: 05-Jan-2023 Contributor: E. Labelle (Information source: DDG Ahab) The Issue: The silencing effect of Montino (silence) is meant to wear off, but it does not. The fix: Adjust wrong variable pointer, added missing line of code. Why this fix: To have the Montino (silence) effect to wear off as intended. Source Disk: Wiz1B.dsk File: COMBAT3.TEXT Segment: PROCEDURE HEALHEAR; (* P010623 *) Code From: BEGIN FOR X := 0 TO ALIVECNT - 1 DO IF BATTLERC[ GROUPI].A.TEMP04[ ALIVECNT].INAUDCNT > 0 THEN BATTLERC[ GROUPI].A.TEMP04[ ALIVECNT].INAUDCNT := BATTLERC[ GROUPI].A.TEMP04[ ALIVECNT].INAUDCNT - 1 END; (* DECINAUD *) BEGIN (* HEALHEAR *) DECINAUD( 0, PARTYCNT); DECINAUD( 1, BATTLERC[ 1].A.ALIVECNT); DECINAUD( 2, BATTLERC[ 2].A.ALIVECNT); DECINAUD( 3, BATTLERC[ 3].A.ALIVECNT) END; (* HEALHEAR *) Code To: BEGIN FOR X := 0 TO ALIVECNT - 1 DO (* WC009 FROM -[ ALIVECNT]- TO -[ X]- *) IF BATTLERC[ GROUPI].A.TEMP04[ X].INAUDCNT > 0 THEN BATTLERC[ GROUPI].A.TEMP04[ X].INAUDCNT := BATTLERC[ GROUPI].A.TEMP04[ X].INAUDCNT - 1 END; (* DECINAUD *) BEGIN (* HEALHEAR *) DECINAUD( 0, PARTYCNT); DECINAUD( 1, BATTLERC[ 1].A.ALIVECNT); DECINAUD( 2, BATTLERC[ 2].A.ALIVECNT); DECINAUD( 3, BATTLERC[ 3].A.ALIVECNT); (* WC009 ADDED NEXT LINE WAS MISSING LAST GROUP OF MONSTERS *) DECINAUD( 4, BATTLERC[ 4].A.ALIVECNT) END; (* HEALHEAR *) Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC010 - Regeneration Degeneration ================================================= Status: Fixed. Recompiled. Verified. Date of change: 06-Jan-2023 Contributor: E. Labelle (Information source: DDG Ahab) The Issue: HEALPTS (hit points regeneration and degeneration) is probably meant to stack but instead, it just takes whatever item has the biggest heal value. Consequently, the DEADLY RING's HP draining property has no effect. The fix: Adjust code to have regeneration and degeneration items stack. Poison and stacking poison from chest traps are also taken in account. Why this fix: To have regeneration and degeneration effects stack. The Deadly Ring is now actually deadly. Source Disk: Wiz1B.dsk File: UTILITIE2.TEXT Segment: PROCEDURE NORMPOW; (* P01011D *) Code From: IF CHARACTR[ CHARI].HEALPTS < OBJECT.HEALPTS THEN CHARACTR[ CHARI].HEALPTS := OBJECT.HEALPTS; Code To: (* WC010 MAKE OBJECT REGEN STACK AND INCLUDE NEGATIVE AMOUNTS *) (* REMOVE -IF CHARACTR[ CHARI].HEALPTS < OBJECT.HEALPTS THEN- *) (* REMOVE -CHARACTR[ CHARI].HEALPTS := OBJECT.HEALPTS;- *) (* ADD NEXT LINE *) CHARACTR[ CHARI].HEALPTS := CHARACTR[ CHARI].HEALPTS + OBJECT.HEALPTS; Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC011 - Monster Affliction Dispel ================================================= Status: Fixed. Recompiled. Verified. Date of change: 07-Jan-2023 Contributor: E. Labelle (Information source: DDG Ahab) The Issue: Dispel does not work on undead monsters with status afflictions. This would be a pretty rare occurrence though; Katino doesn't work on the undead, and casting Manifo when you can just dispel them is a bit crazy. The fix: Adjust code to have dispel work on monsters that have an affliction. Why this fix: To have dispel work on monsters that have an affliction. Source Disk: Wiz1B.dsk File: COMBAT5.TEXT Segment: PROCEDURE DODISPEL; (* P010913 *) Code From: IF BATTLERC[ VICTIM].A.TEMP04[ CHARX].STATUS = OK THEN Code To: (* WC011 FROM -= OK- TO -< DEAD- *) IF BATTLERC[ VICTIM].A.TEMP04[ CHARX].STATUS < DEAD THEN Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC012 - Mamorlis ================================ Status: Fixed. Recompiled. Verified. Date of change: 09-Jan-2023 Contributor: E. Labelle The Issue: Mamorlis is supposed to fear all the monsters (reduce their armor class by 3) but the 1st monster of each group is not affected. The fix: Adjust code to have all monsters affected. Why this fix: To have all monsters affected. Source Disk: Wiz1B.dsk File: COMBAT4.TEXT Segment: PROCEDURE DOMAGE; (* P01081C *) Code From: IF SPELL = MAMORLIS THEN FOR GROUPI := 1 TO 4 DO MODAC( GROUPI, -3, 1, BATTLERC[ GROUPI].A.ALIVECNT); Code To: IF SPELL = MAMORLIS THEN FOR GROUPI := 1 TO 4 DO (* WC012 FROM -1-, -ALIVECNT- TO -0-, -ALIVECNT - 1- *) MODAC( GROUPI, -3, 0, BATTLERC[ GROUPI].A.ALIVECNT - 1); Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC013 - Mabadi ============================== Status: Fixed. Recompiled. Verified. Date of change: 11-Jan-2023 Contributor: E. Labelle The Issue: Monsters " IS HIT BY MABADI!" message is displayed although no monsters are left alive. The fix: Added code to skip that effect and message if the monster is dead. Also, removed an extra space at the beginning of " IS HIT...". Why this fix: To skip the Mabadi effect and message if the monster is dead. Source Disk: Wiz1B.dsk File: COMBAT4.TEXT Segment: PROCEDURE DOPRIEST; (* P01081B *) Code From: IF SPELL = MABADI THEN BEGIN CLRRECT( 1, 12, 38, 3); MVCURSOR( 1, 12); DSPNAMES( CASTGR, CASTI); PRINTSTR( ' IS HIT BY MABADI!'); BATTLERC[ CASTGR].A.TEMP04[ CASTI].HPLEFT := 1 + (RANDOM MOD 8); END; Code To: IF SPELL = MABADI THEN (* WC013 ADD NEXT LINE *) IF BATTLERC[ CASTGR].A.TEMP04[ CASTI].STATUS < DEAD THEN BEGIN CLRRECT( 1, 12, 38, 3); MVCURSOR( 1, 12); DSPNAMES( CASTGR, CASTI); (* WC013 REMOVE EXTRA BEGINNING SPACE *) PRINTSTR( 'IS HIT BY MABADI!'); BATTLERC[ CASTGR].A.TEMP04[ CASTI].HPLEFT := 1 + (RANDOM MOD 8); END; Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC014 - Manifo ============================== Status: Fixed. Recompiled. Verified. Date of change: 14-Jan-2023 Contributor: E. Labelle (Information source: DDG Ahab) The Issue: Monsters affected by Manifo wrongly get the status Asleep instead of Paralyzed. Monster resistance to Manifo is so high that the spell is essentially useless. The fix: Adjust the code so that the monsters have the status PLYZE instead of ASLEEP if affected by Manifo. Reduce the monsters' resistance to Manifo so that it now sits in between the original setting and Legacy of Llylgamyn (over-powered). Ex: Now a level 3 monster has a 65% chance to resist Manifo, compared to a 60% chance to resist Katino. The second fix was done out of necessity and for negligeable coding space (less than 512 bytes left on disk for coding) and can easily be reversed or changed if necessary. Why this fix: To make the Manifo spell work as intended. Also, this makes use of the code that is already in the game for the monsters to recuperate from a paralysis effect. Make Manifo a useful spell. Source Disk: Wiz1B.dsk File: COMBAT4.TEXT Segment: PROCEDURE ISISNOT( GROUPI: INTEGER; (* P010804 *) PROCEDURE DOHOLD; (* P010809 *) Code From: BEGIN PRINTSTR( 'IS '); CASE DAMTYPE OF 0, 3: BATTLERC[ GROUPI].A.TEMP04[ CHARI].STATUS := ASLEEP; 1: BATTLERC[ GROUPI].A.TEMP04[ CHARI].INAUDCNT := (RANDOM MOD 4) + 2; 2: BEGIN BATTLERC[ GROUPI].A.TEMP04[ CHARI].STATUS := DEAD; BATTLERC[ GROUPI].A.TEMP04[ CHARI].HPLEFT := 0 END END END; Code To: BEGIN PRINTSTR( 'IS '); CASE DAMTYPE OF (* WC014 ENABLED PARALYZE EFFECTS *) 0: BATTLERC[ GROUPI].A.TEMP04[ CHARI].STATUS := PLYZE; 1: BATTLERC[ GROUPI].A.TEMP04[ CHARI].INAUDCNT := (RANDOM MOD 4) + 2; 2: BEGIN BATTLERC[ GROUPI].A.TEMP04[ CHARI].STATUS := DEAD; BATTLERC[ GROUPI].A.TEMP04[ CHARI].HPLEFT := 0 END; 3: BATTLERC[ GROUPI].A.TEMP04[ CHARI].STATUS := ASLEEP END END; Code From: ISISNOT( CASTGR, CHARX, 50 + 10 * BATTLERC[ CASTGR].B.HPREC.LEVEL , 'HELD', 0) Code To: (* WC014 FROM -10 *- TO -5 *- *) ISISNOT( CASTGR, CHARX, 50 + 5 * BATTLERC[ CASTGR].B.HPREC.LEVEL , 'HELD', 0) Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC015 - To Hit ============================== Status: Fixed. Recompiled. Verified. Date of change: 17-Jan-2023. Contributor: E. Labelle (Information source: DDG Ahab). The Issue: Monsters in the front row were harder to hit than monsters in the back row, which made no sense. The fix: The variable VICTIM is monster groups 1 to 4. Changed the code to: "+ ((3 * VICTIM) - 6);". Extra set of parentheses here to make sure nothing stupid happens and for clarity. This way, the chance to hit the first monster group does not change, i.e., -3 (-15%), a minus number here is good, but each subsequent monster groups are harder to hit by 3 (15%). Why this fix: To make the "To Hit" chance against the monsters work properly and logically. Source Disk: Wiz1B.dsk File: COMBAT5.TEXT Segment: PROCEDURE DAM2ENMY; (* P01090F *) Code From: HPCALCPC := 21 - BATTLERC[ VICTIM].B.AC - CHARACTR[ BATI].HPCALCMD + BATTLERC[ VICTIM].A.TEMP04[ SINGLEX].ARMORCL - 3 * VICTIM; Code To: HPCALCPC := 21 - BATTLERC[ VICTIM].B.AC - CHARACTR[ BATI].HPCALCMD + BATTLERC[ VICTIM].A.TEMP04[ SINGLEX].ARMORCL + ((3 * VICTIM) - 6); (* WC015 FROM - 3 * VICTIM *) Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC016 - Luck (LUCKSKIL) ======================================= Status: Fixed. Recompiled. Verified. Date of change: 24-Jan-2023. Contributor: E. Labelle (Information source: E. Labelle, DDG Ahab). The Issue: Saving throws inconsistency. The fix: Saving throws are based on your character's Luck attribute and a modifier. After a long analysis, everything jives except for saving vs the chests' Poison Gas Trap. It pointed to "3" (Breath) attack, changed it to "2". Wizardry matches the 1979 AD&D Saving Throw table (http://grognardia.blogspot.com/2020/12/saving-throws.html). Detailed information at the end of this issue. Why this fix: This makes use of saving throw category "2", and it did not make sense for the Poison Gas Trap and Breath Attack being in the same category. Source Disk: Wiz1C.dsk File: REWARDS.TEXT Segment: PROCEDURE TYPE3DAM; (* P010D11 *) Code From: 2: (* GAS *) FOR CHARX := 0 TO PARTYCNT - 1 DO IF (RANDOM MOD 20) < CHARACTR[ CHARX].LUCKSKIL[ 3] THEN CHARACTR[ CHARX].LOSTXYL.POISNAMT[ 1] := 1; Code To: 2: (* GAS *) FOR CHARX := 0 TO PARTYCNT - 1 DO (* WC016 FROM -[ 3]- TO -[ 2]- *) IF (RANDOM MOD 20) < CHARACTR[ CHARX].LUCKSKIL[ 2] THEN CHARACTR[ CHARX].LOSTXYL.POISNAMT[ 1] := 1; Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Details: There are the 5 saving throw checks used in the game: 0 - Poison & Paralysis & Critical Hit (Special monster skills). 1 - Stone. 2 - Was not used, moved the Poison Gas Chest Trap here. 3 - Breath. Poison Gas Chest Trap, made no sense, moved to 2. 4 - Silence. Anti-Mage/Anti-Priest Chest Traps. Here are the compiled resistances, after changes, each point is 5%: - [0] Vs. Poison & Paralysis & Critical Hit: Fighter 15%, Samurai 10%, Lord 10%, Ninja 15%, and if race is Human 5%. - [1] Vs. Stoning: Priest 15%, Bishop 10%, Lord 10%, Ninja 10%, and if race is Gnome 10%. - [2] Vs. Poison Gas Chest Trap: Bishop 10%, Ninja 20%, and if race is Elf 10%. - [3] Vs. Breath Attacks: Thief 15%, Ninja 15%, and if race is Dwarf 20% to reduce the Breath damage by half. - [4] Vs. Anti-Mage and Anti-Priest chest trap and Silence: Mage 15%, Bishop 10%, Samurai 10%, Ninja 10%, and if the race is Hobbit 15%. - Vs. all of the above: add 5% for every 5 Levels of your character. - Vs. all of the above: add 5% if your Luck is 6, 10% if your Luck is 12, and 15% if your Luck is 18. LUCKSKIL analysis: wiz --- PROGRAM WIZARDRY; TCHAR = RECORD LUCKSKIL : PACKED ARRAY[ 0..4] OF 0..31; roller ------ PROCEDURE MAKECHAR; (* P010B09 *) PROCEDURE INITCHAR; (* P010B0A *) VAR LSI : INTEGER; UNUSED : INTEGER; BEGIN FILLCHAR( CHARREC, SIZEOF( CHARREC), 0); CHARREC.NAME := CHARNAME; CHARREC.AGE := (18 * 52) + (RANDOM MOD 300); CHARREC.GOLD.LOW := 90 + (RANDOM MOD 100); CHARREC.STATUS := OK; FOR LSI := 0 TO 4 DO BEGIN CHARREC.LUCKSKIL[ LSI] := 16 END; CHARREC.MAXLEVAC := 1; CHARREC.CHARLEV := 1; CHARREC.ARMORCL := 10 END; utilitie2 --------- PROCEDURE UPLCKSKL( LSSUB: INTEGER; (* P010123 *) LSMODAMT: INTEGER); BEGIN LSMODAMT := CHARACTR[ CHARI].LUCKSKIL[ LSSUB] - LSMODAMT; IF LSMODAMT < 1 THEN LSMODAMT := 1; CHARACTR[ CHARI].LUCKSKIL[ LSSUB] := LSMODAMT END; PROCEDURE INITSTUF; (* P010124 *) VAR X : INTEGER; Y : INTEGER; BEGIN WITH CHARACTR[ CHARI] DO BEGIN FOR X := 0 TO 13 DO BEGIN WEPVSTY2[ 0][ X] := FALSE; WEPVSTY2[ 1][ X] := FALSE; WEPVSTYP[ X] := FALSE END; FOR Y := 0 TO 6 DO BEGIN WEPVSTY3[ 0][ Y] := FALSE; WEPVSTY3[ 1][ Y] := FALSE END END END; BEGIN (* EQUIPCHR *) WITH CHARACTR[ CHARI] DO BEGIN TEMPX := (20 - CHARLEV DIV 5) - (ATTRIB[ LUCK] DIV 6); IF TEMPX < 1 THEN TEMPX := 1; FOR LUCKI := 0 TO 4 DO LUCKSKIL[ LUCKI] := TEMPX; CASE CLASS OF FIGHTER : UPLCKSKL( 0, 3); MAGE : UPLCKSKL( 4, 3); PRIEST : UPLCKSKL( 1, 3); THIEF : UPLCKSKL( 3, 3); BISHOP : BEGIN UPLCKSKL( 2, 2); UPLCKSKL( 4, 2); UPLCKSKL( 1, 2); END; SAMURAI : BEGIN UPLCKSKL( 0, 2); UPLCKSKL( 4, 2); END; LORD : BEGIN UPLCKSKL( 0, 2); UPLCKSKL( 1, 2); END; NINJA : BEGIN UPLCKSKL( 0, 3); UPLCKSKL( 1, 2); UPLCKSKL( 2, 4); UPLCKSKL( 3, 3); UPLCKSKL( 4, 2); END; END; CASE RACE OF HUMAN: UPLCKSKL( 0, 1); ELF: UPLCKSKL( 2, 2); DWARF: UPLCKSKL( 3, 4); GNOME: UPLCKSKL( 1, 2); HOBBIT: UPLCKSKL( 4, 3); END; rewards ------- BEGIN (* ANTIPM *) FOR CHARPM := 0 TO PARTYCNT - 1 DO BEGIN PLYZSTON := (RANDOM MOD 20) < CHARACTR[ CHARPM].LUCKSKIL[ 4]; CASE CHARACTR[ CHARPM].CLASS OF MAGE: IF BMAGEDAM THEN IF PLYZSTON THEN ISPLYZE ELSE ISSTONED; SAMURAI: IF BMAGEDAM THEN IF NOT PLYZSTON THEN ISPLYZE; PRIEST: IF NOT BMAGEDAM THEN IF PLYZSTON THEN ISPLYZE ELSE ISSTONED; BISHOP: IF NOT BMAGEDAM THEN IF NOT PLYZSTON THEN (* IF NOT SET... *) ISPLYZE; END END END; (* ANTIPM *) . . . BEGIN (* DOTRAPDM *) CLRRECT( 13, 8, 26, 2); MVCURSOR( 13, 8); IF TRAPTYPE <> 0 THEN BEGIN PRINTSTR( 'OOPPS! A '); PRTRAPTY( TRAPTYPE, TRAP3TYP) END ELSE PRINTSTR( 'THE CHEST WAS NOT TRAPPED'); PAUSE2; CASE TRAPTYPE OF 1: (* POISON *) CHARACTR[ CHRXCHST].LOSTXYL.POISNAMT[ 1] := CHARACTR[ CHRXCHST].LOSTXYL.POISNAMT[ 1] + 1; 2: (* GAS *) FOR CHARX := 0 TO PARTYCNT - 1 DO IF (RANDOM MOD 20) < CHARACTR[ CHARX].LUCKSKIL[ 3] THEN CHARACTR[ CHARX].LOSTXYL.POISNAMT[ 1] := 1; combat4 ------- PROCEDURE DOSILENC; (* P01080A *) VAR CHARX : INTEGER; BEGIN FOR CHARX := 0 TO BATTLERC[ CASTGR].A.ALIVECNT - 1 DO IF CASTGR = 0 THEN ISISNOT( CASTGR, CHARX, 100 - 5 * CHARACTR[ CHARX].LUCKSKIL[ 4], 'SILENCED', 1) ELSE ISISNOT( CASTGR, CHARX, 10 * BATTLERC[ CASTGR].B.HPREC.LEVEL, 'SILENCED', 1) END; combat5 ------- PROCEDURE RESULT( ATTK0123: INTEGER; (* P01090B *) STONFLAG: INTEGER; POISSTON: INTEGER; DAMSTR: STRING); VAR CHANCBAD : INTEGER; BEGIN IF (RANDOM MOD 20) > CHARACTR[ MYVICTIM].LUCKSKIL[ STONFLAG] THEN EXIT( RESULT); IF ATTK0123 = 3 THEN BEGIN CHANCBAD := BATTLERC[ BATG].B.HPREC.LEVEL * 2; IF CHANCBAD > 50 THEN CHANCBAD := 50; IF (RANDOM MOD 100) > CHANCBAD THEN EXIT( RESULT) END; IF POISSTON > 0 THEN IF CHARACTR[ MYVICTIM].WEPVSTY3[ 1][ POISSTON] THEN EXIT( RESULT); IF CHARACTR[ MYVICTIM].STATUS >= DEAD THEN EXIT( RESULT); CLRRECT( 1, 14, 38, 1); MVCURSOR( 1, 14); PRNAME( 0, MYVICTIM); PRINTSTR( 'IS '); PRINTSTR( DAMSTR ); CASE ATTK0123 OF 0: IF BATTLERC[ 0].A.TEMP04[ MYVICTIM].STATUS < STONED THEN BATTLERC[ 0].A.TEMP04[ MYVICTIM].STATUS := STONED; 1: CHARACTR[ MYVICTIM].LOSTXYL.POISNAMT[ 1] := 1; 2: IF BATTLERC[ 0].A.TEMP04[ MYVICTIM].STATUS < PLYZE THEN BATTLERC[ 0].A.TEMP04[ MYVICTIM].STATUS := PLYZE; 3: BEGIN BATTLERC[ 0].A.TEMP04[ MYVICTIM].STATUS := DEAD; BATTLERC[ 0].A.TEMP04[ MYVICTIM].HPLEFT := 0 END END; PAUSE1 END; (* RESULT *) BEGIN (* CASEDAMG *) WITH BATTLERC[ BATG].B DO BEGIN IF SPPC[ 1] THEN RESULT( 1, 0, 3, 'POISONED'); IF SPPC[ 2] THEN RESULT( 2, 0, 0, 'PARALYZED'); IF SPPC[ 0] THEN RESULT( 0, 1, 5, 'STONED'); IF DRAINAMT > 0 THEN DRAINLEV; IF SPPC[ 3] THEN RESULT( 3, 0, 0, 'CRITICALLY HIT') END END; (* CASEDAMG *) combat5 ------- PROCEDURE DOBREATH; (* P010906 *) VAR UNUSED : INTEGER; HITDAM : INTEGER; CHARX : INTEGER; BEGIN PRINTSTR( 'BREATHES!'); FOR CHARX := 0 TO PARTYCNT - 1 DO BEGIN IF BATTLERC[ 0].A.TEMP04[ CHARX].STATUS < DEAD THEN BEGIN CLRRECT( 1, 12, 38, 3); MVCURSOR( 1, 12); HITDAM := BATTLERC[ BATG].A.TEMP04[ BATI].HPLEFT DIV 2; IF (RANDOM MOD 20) >= CHARACTR[ CHARX].LUCKSKIL[ 3] THEN HITDAM := (HITDAM + 1) DIV 2; IF CHARACTR[ CHARX].WEPVSTY3[ 1][ BATTLERC[ BATG].B.BREATHE] THEN HITDAM := (HITDAM + 1) DIV 2; UNAFFECT( 0, CHARX, HITDAM) END END END; PROCEDURE RESULT( ATTK0123: INTEGER; (* P01090B *) STONFLAG: INTEGER; POISSTON: INTEGER; DAMSTR: STRING); VAR CHANCBAD : INTEGER; BEGIN IF (RANDOM MOD 20) > CHARACTR[ MYVICTIM].LUCKSKIL[ STONFLAG] THEN EXIT( RESULT); . . . BEGIN (* CASEDAMG *) WITH BATTLERC[ BATG].B DO BEGIN IF SPPC[ 1] THEN RESULT( 1, 0, 3, 'POISONED'); IF SPPC[ 2] THEN RESULT( 2, 0, 0, 'PARALYZED'); IF SPPC[ 0] THEN RESULT( 0, 1, 5, 'STONED'); Bug/Issue #: WC017 - Camp Use Item Screen Update =================================================== Status: Fixed. Recompiled. Verified. Date of change: 25-Jan-2023. Contributor: E. Labelle. The Issue: When in Camp, if using an item and it decays (Ex: Dios Potion > Broken Item), the display still shows the undecayed item name. The fix: Add a line of code to refresh the items list after an item has been used. Why this fix: To have the correct items' names displayed after use. Source Disk: Wiz1C.dsk File: CAMP.TEXT Segment: PROCEDURE USEITEM; (* P010C11 *) Code From: CASTSPEL( SCNTOC.SPELLHSH[ THEITEM.SPELLPWR]) Code To: CASTSPEL( SCNTOC.SPELLHSH[ THEITEM.SPELLPWR]); (* WC017 ADD NEXT LINE *) DSPITEMS Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Enhancement #: WC018 - Display Hit Probability =============================================== Status: Fixed. Recompiled. Verified. Date of change: 27-Jan-2023. Contributor: E. Labelle. The Issue: Enhance the battle details display by showing the hit probability of characters and monsters on-the-fly. The fix: Added code to accomplish this. Why this fix: Enhance the display of battle information. Source Disk: Wiz1B.dsk File: COMBAT5.TEXT Segments: PROCEDURE DOFIGHT; (* P010907 *) PROCEDURE DAM2ME; (* P010908 *) PROCEDURE DAM2ENMY; (* P01090F *) Code From: N/A. Code To: PROCEDURE DOFIGHT; (* P010907 *) (* WC018 DISPLAY HIT PROBABILITY *) PROCEDURE HITPROB( HITP: INTEGER); BEGIN PRINTSTR( 'WITH A HIT PROB OF '); PRINTNUM( (20 - HITP) * 5, 2); PRINTSTR( '%') END; . . . PROCEDURE DAM2ME; (* P010908 *) ... (* WC018 DISPLAY HIT PROBABILITY *) PRINTSTR( ' '); HITPROB( HPCALCPC); . . . PROCEDURE DAM2ENMY; (* P01090F *) ... HITPROB( HPCALCPC); (* WC018 DISPLAY HIT PROBABILITY *) Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Enhancement #: WC019 - Remove Password Prompts =============================================== Status: Fixed. Recompiled. Verified. Date of change: 29-Jan-2023. Contributor: E. Labelle. The Issue: Cannot add any more code since the floppy disk is full. The fix: Removed all the code pertaining to passwords. Why this fix: To make a good chunck of disk space availble for code. Passwords for characters are not necessary. Source Disk: Wiz1C.dsk File: CASTLE.TEXT ROLLER.TEXT Segments: PROCEDURE GETPASS( VAR PASSWORD: STRING); (* P010A02 *) - This segment appears twice PROCEDURE ADDPARTY; (* P010A09 *) PROCEDURE CHGPASS; (* P010B1C *) PROCEDURE TRAINING; (* P010B16 *) PROCEDURE MAKEMENU; (* P010B0D *) Removed code from: CASTLE.TEXT 6536 16 2:D 1 PROCEDURE GETPASS( VAR PASSWORD: STRING); (* P010A02 *) 6537 16 2:D 2 6538 16 2:D 2 VAR 6539 16 2:D 2 UNUSEDXX : INTEGER; 6540 16 2:D 3 RANDX : INTEGER; 6541 16 2:D 4 CHRCNT : INTEGER; 6542 16 2:D 5 6543 16 2:0 0 BEGIN 6544 16 2:1 0 CHRCNT := 0; 6545 16 2:1 3 REPEAT 6546 16 2:2 3 GETKEY; 6547 16 2:2 6 IF INCHAR <> CHR( CRETURN) THEN 6548 16 2:3 11 IF CHRCNT < 15 THEN 6549 16 2:4 16 BEGIN 6550 16 2:5 16 FOR RANDX := 0 TO (RANDOM MOD 2) DO 6551 16 2:6 33 WRITE( CHR( 88)); 6552 16 2:5 48 CHRCNT := CHRCNT + 1; 6553 16 2:5 53 PASSWORD[ CHRCNT] := INCHAR 6554 16 2:4 55 END 6555 16 2:3 57 ELSE 6556 16 2:4 59 WRITE( CHR(7)) 6557 16 2:1 67 UNTIL INCHAR = CHR( CRETURN); 6558 16 2:1 72 WRITELN; 6559 16 2:1 78 PASSWORD[ 0] := CHR( CHRCNT) 6560 16 2:0 81 END; (* GETPASS *) PROCEDURE ADDPARTY; (* P010A09 *) 6725 16 9:1 270 GOTOXY( 0, 20); 6726 16 9:1 275 WRITE( 'ENTER PASSWORD >'); 6727 16 9:1 302 GETPASS( CHARNAME); 6728 16 9:1 306 GOTOXY( 0, 21); 6729 16 9:1 311 IF CHARNAME <> CHARACTR[ PARTYCNT].PASSWORD THEN 6730 16 9:2 324 EXITADDP( '** THATS NOT IT **'); Removed code from: ROLLER.TEXT 7412 17 2:D 1 PROCEDURE GETPASS( VAR PASSWORD: STRING); (* P010B02 *) 7413 17 2:D 2 7414 17 2:D 2 VAR 7415 17 2:D 2 UNUSEDXX : INTEGER; 7416 17 2:D 3 RANDX : INTEGER; 7417 17 2:D 4 CHRCNT : INTEGER; 7418 17 2:D 5 7419 17 2:0 0 BEGIN 7420 17 2:1 0 CHRCNT := 0; 7421 17 2:1 3 REPEAT 7422 17 2:2 3 GETKEY; 7423 17 2:2 6 IF INCHAR <> CHR( CRETURN) THEN 7424 17 2:3 11 IF CHRCNT < 15 THEN 7425 17 2:4 16 BEGIN 7426 17 2:5 16 FOR RANDX := 0 TO (RANDOM MOD 2) DO 7427 17 2:6 33 WRITE( CHR( 88)); 7428 17 2:5 48 CHRCNT := CHRCNT + 1; 7429 17 2:5 53 PASSWORD[ CHRCNT] := INCHAR 7430 17 2:4 55 END 7431 17 2:3 57 ELSE 7432 17 2:4 59 WRITE( CHR( 7)); 7433 17 2:1 67 UNTIL INCHAR = CHR( CRETURN); 7434 17 2:1 72 WRITELN; 7435 17 2:1 78 PASSWORD[ 0] := CHR( CHRCNT) 7436 17 2:0 81 END; 8082 17 28:D 1 PROCEDURE CHGPASS; (* P010B1C *) 8083 17 28:D 1 8084 17 28:D 1 VAR 8085 17 28:D 1 NEWPASS2 : STRING[ 40]; 8086 17 28:D 22 NEWPASS1 : STRING[ 40]; 8087 17 28:D 43 8088 17 28:0 0 BEGIN; 8089 17 28:1 0 WRITE( CHR(12)); 8090 17 28:1 8 WRITE( 'ENTER NEW PASSWORD ([RET] FOR NONE)'); 8091 17 28:1 53 REPEAT 8092 17 28:2 53 GOTOXY( 10, 2); 8093 17 28:2 58 GETPASS( NEWPASS1) 8094 17 28:1 60 UNTIL LENGTH( NEWPASS1) <= 15; 8095 17 28:1 70 WRITE( CHR( 12)); 8096 17 28:1 78 WRITE( 'ENTER AGAIN TO BE SURE'); 8097 17 28:1 110 REPEAT 8098 17 28:2 110 GOTOXY( 10, 2); 8099 17 28:2 115 GETPASS( NEWPASS2) 8100 17 28:1 117 UNTIL LENGTH( NEWPASS2) <= 15; 8101 17 28:1 127 WRITE( CHR( 12)); 8102 17 28:1 135 IF NEWPASS1 = NEWPASS2 THEN 8103 17 28:2 143 BEGIN 8104 17 28:3 143 CHARREC.PASSWORD := NEWPASS1; 8105 17 28:3 150 PUTCHARC( CHARREC, CHARACX); 8106 17 28:3 158 GTSCNTOC; 8107 17 28:3 160 WRITE( 'PASSWORD CHANGED - ') 8108 17 28:2 189 END 8109 17 28:1 189 ELSE 8110 17 28:2 191 BEGIN 8111 17 28:3 191 WRITELN( 'THEY ARE NOT THE SAME - YOUR PASSWORD'); 8112 17 28:3 244 WRITELN( 'HAS NOT BEEN CHANGED!'); 8113 17 28:3 281 WRITELN 8114 17 28:2 281 END; 8115 17 28:1 287 WRITE( 'PRESS [RET]'); 8116 17 28:1 308 GOTOXY( 41, 0); 8117 17 28:1 313 READLN 8118 17 28:0 313 END; PROCEDURE TRAINING; (* P010B16 *) ... 8125 17 22:3 8 REPEAT 8126 17 22:4 8 GOTOXY( 9, 10); 8127 17 22:4 13 WRITE( 'PASSWORD >'); 8128 17 22:4 33 GETPASS( PASSSTR) 8129 17 22:3 35 UNTIL LENGTH( PASSSTR) <= 15; 8130 17 22:3 45 IF PASSSTR <> CHARREC.PASSWORD THEN 8131 17 22:4 54 EXIT( TRAINING) ... Code from: 8157 17 22:2 348 WRITELN( 'C)HANGE CLASS,' : 23); Code to: 8157 17 22:2 348 WRITELN( 'C)HANGE CLASS, OR' : 26); ... 8158 17 22:2 379 WRITELN( 'S)ET NEW PASSWORD, OR' : 29); ... 8178 17 22:2 516 'S': CHGPASS; PROCEDURE MAKEMENU; (* P010B0D *) 7591 17 13:D 1 VAR 7592 17 13:D 1 PASSWD : STRING; ... Code from: 7598 17 13:1 39 WRITELN( 'PASSWORD': 9); Code to: 7598 17 13:1 39 WRITELN( '': 9); ... 7613 17 13:1 301 REPEAT 7614 17 13:2 301 P010B0B; 7615 17 13:2 303 WRITELN( 'ENTER A PASSWORD ([RET] FOR NONE)'); 7616 17 13:2 352 GOTOXY( 10, 1); 7617 17 13:2 357 WRITE( CHR( 29)); 7618 17 13:2 365 GOTOXY( 10, 1); 7619 17 13:2 370 GETPASS( CHARNAME); 7620 17 13:2 375 IF LENGTH( CHARNAME) > 15 THEN 7621 17 13:3 384 CHARNAME := COPY( CHARNAME, 1, 15); 7622 17 13:2 401 P010B0B; 7623 17 13:2 403 WRITELN( 'ENTER IT AGAIN TO BE SURE'); 7624 17 13:2 444 GOTOXY( 10, 1); 7625 17 13:2 449 WRITE( CHR( 29)); 7626 17 13:2 457 GOTOXY( 10, 1); 7627 17 13:2 462 GETPASS( PASSWD); 7628 17 13:1 466 UNTIL PASSWD = CHARNAME; 7629 17 13:1 475 CHARREC.PASSWORD := CHARNAME Final Compiled File Name: WIZARDRY.CODE Destination Disks: Any Wizardry Proving Grounds boot and scenario disks. Enhancement #: WC020 - Show Spells During Combat ================================================= Status: Fixed. Recompiled. Verified. Date of change: 03-Feb-2023. Contributor: E. Labelle. Enhancement suggested by DDG Ahab. The issue: It would be nice to see what spells the monsters are casting. The fix: Added code to show what spells are cast by both the monsters and characters in the combat window. Why this fix: This is a useful and nice enhancement of the combat display details. Source disks: Wiz1A.dsk, Wiz1B.dsk Files: WIZ.TEXT WIZ2.TEXT COMBAT4.TEXT Segments: FORWARD DECLARATIONS PROGRAM WIZARDRY SEGMENT PROCEDURE CASTASPE; (* P010801 *) Add code to: WIZ.TEXT (* ---------- BEGIN FORWARD DECLARATIONS ---------- *) . . . PROCEDURE SHOWMP( SPELLINT: INTEGER); FORWARD; (* WC020 SHOW SPELL NAME *) Add code to: WIZ2.TEXT (Note 1: using CASE here will not work because the numbers are bigger than 999.) (Note 2: this was not put in COMBAT4 because of space restrictions.) (Note 3: Although ugly, this is what takes the least lines of code.) PROCEDURE SHOWMP; (* WC020 SHOW SPELL NAME *) BEGIN IF SPELLINT = 4178 THEN PRINTSTR( 'HALITO'); IF SPELLINT = 2409 THEN PRINTSTR( 'MOGREF'); IF SPELLINT = 3983 THEN PRINTSTR( 'KATINO'); IF SPELLINT = 3245 THEN PRINTSTR( 'DUMAPIC'); IF SPELLINT = 3340 THEN PRINTSTR( 'DILTO'); IF SPELLINT = 1953 THEN PRINTSTR( 'SOPIC'); IF SPELLINT = 6181 THEN PRINTSTR( 'MAHALITO'); IF SPELLINT = 4731 THEN PRINTSTR( 'MOLITO'); IF SPELLINT = 4744 THEN PRINTSTR( 'MORLIS'); IF SPELLINT = 3180 THEN PRINTSTR( 'DALTO'); IF SPELLINT = 6156 THEN PRINTSTR( 'LAHALITO'); IF SPELLINT = 7525 THEN PRINTSTR( 'MAMORLIS'); IF SPELLINT = 6612 THEN PRINTSTR( 'MAKANITO'); IF SPELLINT = 4925 THEN PRINTSTR( 'MADALTO'); IF SPELLINT = 6587 THEN PRINTSTR( 'LAKANITO'); IF SPELLINT = 4573 THEN PRINTSTR( 'ZILWAN'); IF SPELLINT = 3990 THEN PRINTSTR( 'MASOPIC'); IF SPELLINT = 1562 THEN PRINTSTR( 'HAMAN'); IF SPELLINT = 3128 THEN PRINTSTR( 'MALOR'); IF SPELLINT = 2597 THEN PRINTSTR( 'MAHAMAN'); IF SPELLINT =11157 THEN PRINTSTR( 'TILTOWAIT'); IF SPELLINT = 1449 THEN PRINTSTR( 'KALKI'); IF SPELLINT = 2301 THEN PRINTSTR( 'DIOS'); IF SPELLINT = 3675 THEN PRINTSTR( 'BADIOS'); IF SPELLINT = 2889 THEN PRINTSTR( 'MILWA'); IF SPELLINT = 2287 THEN PRINTSTR( 'PORFIC'); IF SPELLINT = 3139 THEN PRINTSTR( 'MATU'); IF SPELLINT = 1717 THEN PRINTSTR( 'CALFO'); IF SPELLINT = 2619 THEN PRINTSTR( 'MANIFO'); IF SPELLINT = 5970 THEN PRINTSTR( 'MONTINO'); IF SPELLINT = 5333 THEN PRINTSTR( 'LOMILWA'); IF SPELLINT = 2718 THEN PRINTSTR( 'DIALKO'); IF SPELLINT = 6491 THEN PRINTSTR( 'LATUMAPIC'); IF SPELLINT = 5169 THEN PRINTSTR( 'BAMATU'); IF SPELLINT = 761 THEN PRINTSTR( 'DIAL'); IF SPELLINT = 1253 THEN PRINTSTR( 'BADIAL'); IF SPELLINT = 9463 THEN PRINTSTR( 'LATUMOFIS'); IF SPELLINT = 4322 THEN PRINTSTR( 'MAPORFIC'); IF SPELLINT = 1614 THEN PRINTSTR( 'DIALMA'); IF SPELLINT = 2446 THEN PRINTSTR( 'BADIALMA'); IF SPELLINT = 4396 THEN PRINTSTR( 'LITOKAN'); IF SPELLINT = 1885 THEN PRINTSTR( 'KANDI'); IF SPELLINT = 180 THEN PRINTSTR( 'DI'); IF SPELLINT = 382 THEN PRINTSTR( 'BADI'); IF SPELLINT = 4296 THEN PRINTSTR( 'LORTO'); IF SPELLINT = 547 THEN PRINTSTR( 'MADI'); IF SPELLINT = 759 THEN PRINTSTR( 'MABADI'); IF SPELLINT = 8330 THEN PRINTSTR( 'LOKTOFEIT'); IF SPELLINT = 5514 THEN PRINTSTR( 'MALIKTO'); IF SPELLINT = 6673 THEN PRINTSTR( 'KADORTO') END; Code from: COMBAT4.TEXT BEGIN (* CASTASPE P010801 *) DSPNAMES( BATG, BATI); PRINTSTR( 'CASTS A SPELL'); IF BATTLERC[ BATG].A.TEMP04[ BATI].INAUDCNT > 0 THEN EXITCAST( 'WHICH FAILS TO BECOME AUDIBLE!'); IF FIZZLES > 0 THEN EXITCAST( 'WHICH FIZZLES OUT'); IF BATG = 0 THEN BEGIN CASTGR := BATTLERC[ 0].A.TEMP04[ BATI].VICTIM; IF (CASTGR > 0) AND (CASTGR < 5) THEN IF BATTLERC[ CASTGR].A.ALIVECNT > 0 THEN CASTI := BATI MOD BATTLERC[ CASTGR].A.ALIVECNT; SPELL := BATTLERC[ 0].A.TEMP04[ BATI].SPELLHSH; END ELSE BEGIN CASTGR := 0; CASTI := BATTLERC[ BATG].A.TEMP04[ BATI].VICTIM; SPELL := BATTLERC[ BATG].A.TEMP04[ BATI].SPELLHSH END; MVCURSOR( 1, 12); DOMAGE; DOPRIEST END; (* CASTASPE P010801 *) Code to: COMBAT4.TEXT BEGIN (* CASTASPE P010801 *) DSPNAMES( BATG, BATI); (* WC020 FROM -CASTS A SPELL- TO -CASTS - *) PRINTSTR( 'CASTS '); IF BATG = 0 THEN BEGIN CASTGR := BATTLERC[ 0].A.TEMP04[ BATI].VICTIM; IF (CASTGR > 0) AND (CASTGR < 5) THEN IF BATTLERC[ CASTGR].A.ALIVECNT > 0 THEN CASTI := BATI MOD BATTLERC[ CASTGR].A.ALIVECNT; SPELL := BATTLERC[ 0].A.TEMP04[ BATI].SPELLHSH; END ELSE BEGIN CASTGR := 0; CASTI := BATTLERC[ BATG].A.TEMP04[ BATI].VICTIM; SPELL := BATTLERC[ BATG].A.TEMP04[ BATI].SPELLHSH END; SHOWMP( SPELL); (* WC020 SHOW SPELL NAME *) IF BATTLERC[ BATG].A.TEMP04[ BATI].INAUDCNT > 0 THEN EXITCAST( 'WHICH FAILS TO BECOME AUDIBLE!'); IF FIZZLES > 0 THEN EXITCAST( 'WHICH FIZZLES OUT'); MVCURSOR( 1, 12); DOMAGE; DOPRIEST END; (* CASTASPE P010801 *) Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC021 - Monsters Wrongly Casting Zilwan ======================================================= Status: Fixed. Recompiled. Verified. Date of change: 05-Feb-2023. Contributors: E. Labelle. DDG Ahab. The issue: Some monsters are casting the ZILWAN spell which does abolutely nothing to the player characters. The fix: Changed the monsters' casting of ZILWAN for MADALTO instead. Why this fix: Madalto was the only spell that made sense. Other high level spells like Makanito, Mamorlis, Lakanito, Masopic do nothing at all or nothing useful for the monsters. Source disk: Wiz1B.dsk File: COMBAT2.TEXT Procedure: PROCEDURE GETMAGSP( SPELLLEV: INTEGER); (* P010618 *) Code from: 6: IF TWOTHIRD THEN SPELLCAS := MADALTO ELSE SPELLCAS := ZILWAN; Code to: 6: IF TWOTHIRD THEN SPELLCAS := MADALTO ELSE SPELLCAS := MADALTO; (* WC021 FROM ZILWAN *) Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC022 - Treasure Tables Range Bug ================================================= Status: Fixed. Recompiled. Verified. Date of change: 06-Feb-2023. Contributors: E. Labelle, DDG Ahab, D. Molony. The issue: In short, the lower range of the treasure tables is off by two, and the upper range off by one. The fix: Adjust to code for the monsters' treasure to give the intended treasures. Why this fix: The monsters were not giving the intended range of treasures they were set to in the Wizardry database across all the treasure tables. The most blatant example: the monsters are not supposed to drop a Deadly Ring which is a one-time event in the game. The fix also takes care of a division by zero problem, i-e, x MOD 0. Source disk: Wiz1C.dsk File: REWARDS.TEXT Procedure: PPROCEDURE ITEMREWD; (* P010D1D *) Code from: ITEMINDX := REWARDM.REWDCALC.ITEM.MININDX + (CALCULATE( 1, REWARDM.REWDCALC.ITEM.RANGE, 1)) + (REWARDM.REWDCALC.ITEM.MFACTOR * CHARIIII); Code to: (* WC022 FIX TREASURE TABLE POINTERS *) ITEMINDX := REWARDM.REWDCALC.ITEM.MININDX + (RANDOM MOD (REWARDM.REWDCALC.ITEM.RANGE + 1)) + (REWARDM.REWDCALC.ITEM.MFACTOR * CHARIIII); Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Enhancement #: WC023 - Surprise Round Enhancement ================================================== Status: Fixed. Recompiled. Verified. Date of change: 07-Feb-2023. Contributors: E. Labelle. Suggested by DDG Ahab. The issue: Getting your party wiped out on round one because you got surprised by spellcasters or breathers kills the fun factor in the game. The fix: Modified the code to disallow casting spells and using breath weapons during surprise rounds for both monsters and characters. Why this fix: Wizardry 3 alleviated this by disallowing spells during surprise rounds. Here we are doing the same and also disallowed breath weapons as well. For example: This way your party does not get wiped out on a surprise breath attack round from the Dragon Zombies. Source disk: Wiz1B.dsk File: COMBAT2.TEXT Procedures: PROCEDURE CACTION; (* P010602 *) > BEGIN (* CACTION *) PROCEDURE ENATTACK; (* P010614 *) > BEGIN (* ENATTACK *) Code from: PRINTSTR( 'S)PELL P)ARRY'); . . . 'S': GETSPELL; . . . ENEMYSPL; IF ATTCKTYP = 0 THEN BREATHES; Code to: IF SURPRISE = 0 THEN PRINTSTR( 'S)PELL P)ARRY') ELSE PRINTSTR( 'P)ARRY'); (* WC023 *) . . . 'S': IF SURPRISE = 0 THEN GETSPELL; (* WC023 *) . . . IF SURPRISE = 0 THEN ENEMYSPL; (* WC023 *) IF SURPRISE = 0 THEN IF ATTCKTYP = 0 THEN BREATHES; (* WC023 *) Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Release #: WC024 - Interim Release 09 Feb 2023 =================================================== Status: Fixed. Recompiled. Verified. Date of change: 09-Feb-2023. Contributors: E. Labelle. The issue: Treasure tables 18 and 19 are off of their intended range. Gather all database fixes in one release. Database fixes: Updated treasure tables 18 and 19 and merged the database fixes from Wizardry Restored v2.2. The entire list of database fixes can be found here: https://www.zimlab.com/wizardry/proving-grounds-v3 Why this release: Now that the WC022 Treasure Tables Range Bug has been fixed is is time to make an interim release by updating treasure tables 18 and 19 and merge the database fixes from Wizardry Restored v2.2. Treasure tables change details: Old Rewards Tables before code fix WC022: Min Range Intended Intended Actual Actual Index Range Minimum Maximum Minimum Maximum 18C 79 13 80 92 81 93 19C 78 13 80 92 80 92 New Rewards Tables after code fix WC022, with Min Index and Range corrections: Min Range Intended Intended Actual Actual Index Minimum Maximum Minimum Maximum 18C 80 12 80 92 80 92 19C 80 12 80 92 80 92 Source disk: Wiz1E.dsk File: OPTIONS.TEXT Procedure: SEGMENT PROCEDURE OPTIONS; (* P070301 *) Code from: WRITE( ' VERSION 3.0 OF 04-JAN-23 SER:'); Code to: WRITE( ' VERSION 3.0 OF 09-FEB-23 SER:'); Final compiled file names: SYSTEM.STARTUP and WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC025 - Fix Addlongs vs Experience Points ========================================================= Status: Fixed. Recompiled. Verified. Date of change: 10-Feb-2023. Contributors: E. Labelle. Information from DDG Ahab and Denis Molony. Solution from Thomas Ewers. The issue: The Addlongs procedure that adds two numbers has a bug where part of the first value is passed on to the second value because they have the same name thus having a addition/multiplication side effect. This causes the experience points of some monsters to be artificially high. The fix: Updated the declaration of the procedure to have the second value as a constant. Why this fix: To fix the Addlongs procedure bug. Also, this makes current monsters or future ones in another scenario to have a more predictable experience allocation. Source disk: Wiz1A.dsk File: WIZ.TEXT Procedure: PROCEDURE ADDLONGS (* P010005 *) Code from: PROCEDURE ADDLONGS( VAR FIRST: TWIZLONG; (* P010005 *) VAR SECOND: TWIZLONG); FORWARD; Code to: PROCEDURE ADDLONGS( VAR FIRST: TWIZLONG; (* P010005 *) SECOND: TWIZLONG); FORWARD; (* WC025 FROM -VAR SECOND- TO -SECOND- *) Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC026 - Misspelling Bad Amount ============================================== Status: Fixed. Recompiled. Verified. Date of change: 11-Feb-2023. Contributors: E. Labelle. The issue: When trading gold between two characters, and the amount entered is invalid you get a message. The contraction of a word in that message is slightly annoying and unnecessary. The fix: Changed the message from "Bad Amt" to "Bad Amount". Why this fix: Clarity. To remove the distration caused by the contraction of a word. Source disk: Wiz1C.dsk File: CAMP2.TEXT Procedure: PROCEDURE TRADGOLD; (* P010C19 *) Code from: EXITTRAD( 'BAD AMT'); Code to: EXITTRAD( 'BAD AMOUNT'); (* WC026 FROM -BAD AMT- *) Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Enhancement #: WC027 - Drain Only Once Per Combat Enhancement ============================================================== Status: Fixed. Recompiled. Verified. Date of change: 11-Feb-2023. Contributors: E. Labelle. The issue: Monsters can drain your characters several times during combat. This is killing the fun factor in the game. The fix: Added code for the monsters to not being able to drain your characters if they have already been drained. This includes a character drained by Haman or Mahaman. Although, casting successively Haman or Mahaman will drain your characters each time. Why this fix: The draining effects are now working the same way they are in Wizardry 3 - Legacy of Llylgamyn. Source disk: Wiz1B.dsk File: COMBAT5.TEXT Procedure: PROCEDURE DRAINLEV; (* P01090A *) Code from: IF CHARACTR[ MYVICTIM].WEPVSTY3[ 1][ 4] THEN EXIT( DRAINLEV); Code to: IF DRAINED[ MYVICTIM] OR CHARACTR[ MYVICTIM].WEPVSTY3[ 1][ 4] THEN EXIT( DRAINLEV); (* WC027 ADD -DRAINED[ MYVICTIM] OR- *) Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Enhancement #: WC028 - Loktofeit ================================= Status: Fixed. Recompiled. Verified. Date of change: 12-Feb-2023. Contributors: E. Labelle. The issue: The cast chance and penalty for using Loktofeit is such that it is never used. The fix: Updated the code so that the cast chance is the same as Wizardry 3 - Legacy of Llylgamyn which is (65 + Character Level)%. Why this fix: To have the cast chance align with Legacy of Llylgamyn. Source disk: Wiz1B.dsk File: COMBAT4.TEXT Procedure: PROCEDURE SLOKTOFE; (* P010818 *) Code from: IF (RANDOM MOD 100) > 2 * CHARACTR[ BATI].CHARLEV THEN BEGIN MVCURSOR( 1, 13); PRINTSTR( 'LOKTOFEIT FAILS!'); EXIT( SLOKTOFE) END; Code to: IF (RANDOM MOD 100) > 65 + CHARACTR[ BATI].CHARLEV THEN BEGIN MVCURSOR( 1, 13); PRINTSTR( 'LOKTOFEIT FAILS!'); EXIT( SLOKTOFE) END; Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Release #: WC029 - Interim Release 14 Feb 2023 =================================================== Status: Fixed. Recompiled. Verified. Date of change: 14-Feb-2023. Contributors: E. Labelle. The issue: Interim release due to several new fixes and enhancements since the last release. Also, corrected spelling of contracted words that also were missing the apostrophe. The fix: Updated text display of some words. Why this fix: Interim release. Consistency. Source disks: Wiz1B. Wiz1C. Wiz1E.dsk Files: COMBAT2.TEXT, SHOPS.TEXT, CAMP.TEXT, OPTIONS.TEXT Code from: PRINTSTR( 'YOU DONT KNOW THAT SPELL'); ... AASTRAA( 'YOU CANT CARRY ANYTHING MORE') AASTRAA( '** WE DONT BUY CURSED ITEMS **') AASTRAA( '** YOU CANT AFFORD THE FEE **'); ... EXITCAST( 'YOU CANT CAST IT') EXITCAST( 'YOU CANT CAST IT'); EXITCAST( 'YOU CANT CAST IT'); ... WRITE( ' VERSION 3.0 OF 09-FEB-23 SER:'); Code to: PRINTSTR( 'YOU DO NOT KNOW THAT SPELL'); (* WC029 *) ... AASTRAA( 'YOU CANNOT CARRY ANYTHING MORE') (* WC029 *) AASTRAA( '** WE DO NOT BUY CURSED ITEMS **') (* WC029 *) AASTRAA( '** YOU CANNOT AFFORD THE FEE **'); (* WC029 *) ... EXITCAST( 'YOU CANNOT CAST IT') (* WC029 *) EXITCAST( 'YOU CANNOT CAST IT'); (* WC029 *) EXITCAST( 'YOU CANNOT CAST IT'); (* WC029 *) ... WRITE( ' VERSION 3.0 OF 14-FEB-23 SER:'); Final compiled file names: SYSTEM.STARTUP and WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Enhancement #: WC030 - Ninja Enhancements ========================================== Status: Fixed. Recompiled. Verified. Date of change: 27-Feb-2023. Contributors: Eric Labelle and DDG Ahab. The issue: Ninjas are not living up to their unarmed combat performance promise. Here is the Ninja definition in the Wizardry manual: "NINJA - are inhuman fighting machines. They can use any weapons or armor, but work best without any! When fighting without protection with their bare hands, they can cause havoc and destruction, and may even kill the strongest opponent with a single blow! Their great training gives them a lower and lower ARMOR CLASS as they reach higher and higher levels of ability. However, they get hit points as does a THIEF and gain no spells. Finally, they must be EVIL" Most of everything above concerning unarmed combat does not happen in-game. In 1981 you did not know that prior to playing the game. And if you succeeded (without cheating) in making a ninja, you found out that its unarmed performance was a total heart-breaking disappointment. The result is that essentially nobody played an unarmed ninja. Also, to switch class to ninja you needed 17 in all attributes which is almost impossible to get before the end of the game. The fix: Made these code enhancements: - The requirements to change class to ninja are now 15 in all attributes instead of 17. Must still be of evil alignment. - Base bare hands damage increased from 2d4 to 2d8. - Unarmed Armor Class improved from 1 point every 3 levels, to 1 point every level. - Unarmed Combat Initiative Bonus of 1 point (10%) for every 3 levels. Gives the ninja more chances to strike the monsters first. Note that the ninja has 1 extra attack per round compared to other fighter classes, this has not changed. Critical hit chance has not changed either. Why this fix: Make it worthwhile to role-play an unarmed ninja. Source disk: Wiz1B.dsk File: UTILITIE2.TEXT Procedure: PROCEDURE INITSTUF; (* P010124 *) Code from: IF CLASS = NINJA THEN HPDAMRC.HPFAC := 4; ... IF CHARACTR[ CHARI].CLASS = NINJA THEN IF UNARMED THEN CHARACTR[ CHARI].ARMORCL := (CHARACTR[ CHARI].ARMORCL - (CHARACTR[ CHARI].CHARLEV DIV 3)) - 2 Code to: IF CLASS = NINJA THEN HPDAMRC.HPFAC := 8; (* WC030 FROM -4- TO -8- *) ... IF CHARACTR[ CHARI].CLASS = NINJA THEN IF UNARMED THEN CHARACTR[ CHARI].ARMORCL := (CHARACTR[ CHARI].ARMORCL - (CHARACTR[ CHARI].CHARLEV)) (* WC030 FROM -CHARLEV DIV 3)) - 2- TO -CHARLEV))- *) Source disk: Wiz1B.dsk File: COMBAT2.TEXT Procedure: PROCEDURE CACTION; (* P010602 *) Code From: N/A Code To: ... VAR POSSY : INTEGER; (* WC030 *) UNARMED2 : BOOLEAN; (* WC030 *) ... (* WC030 *) IF CHARACTR[ MYCHARX].CLASS = NINJA THEN BEGIN UNARMED2 := TRUE; FOR POSSY := 1 TO CHARACTR[ MYCHARX].POSS.POSSCNT DO IF CHARACTR[ MYCHARX].POSS.POSSESS[ POSSY].EQUIPED THEN UNARMED2 := FALSE; IF UNARMED2 THEN AGIL1TEN := AGIL1TEN - (CHARACTR[ MYCHARX].CHARLEV DIV 3) END; ... (* PRINTSTR( ' INIT:'); WC030 *) (* PRINTNUM( AGIL1TEN, 2); WC030 *) Note: the last 2 lines above are remarked out, the code was used to verify that the bonus initiative worked. Source disk: Wiz1C.dsk File: ROLLER.TEXT Procedure: SEGMENT PROCEDURE ROLLER; (* P010B01 *) Code From: CHG2LST[ NINJA] := (SIXATTR2[ STRENGTH] >= 17) AND (SIXATTR2[ IQ] >= 17) AND (SIXATTR2[ PIETY] >= 17) AND (SIXATTR2[ VITALITY] >= 17) AND (SIXATTR2[ AGILITY] >= 17) AND (SIXATTR2[ LUCK] >= 17) AND (CHARREC.ALIGN = EVIL); Code To: (* WC030 FROM 17 TO 15 *) CHG2LST[ NINJA] := (SIXATTR2[ STRENGTH] >= 15) AND (SIXATTR2[ IQ] >= 15) AND (SIXATTR2[ PIETY] >= 15) AND (SIXATTR2[ VITALITY] >= 15) AND (SIXATTR2[ AGILITY] >= 15) AND (SIXATTR2[ LUCK] >= 15) AND (CHARREC.ALIGN = EVIL); Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC031 - Mapiro Mahama Diromat ============================================= Status: Fixed. Recompiled. Verified. Date of change: 05-Mar-2023. Contributors: Eric Labelle, suggested by David Kilpatrick. The issue: On level 1, after coming back from the elevators, or from farming the Murphy's Ghosts, there is a shortcut back to the castle. The shortcut happens when you enter a certain room, and the mage therein sends you back to the castle after an incantation. The problem is that part of the message appears and disappears from the screen so fast that you cannot read it. Here is the message: A STRANGE GLOW SEEMS TO EMANATE FROM THIS ROOM. IN THE CENTER, A SMALLISH MAN IN A LONG ROBE TURNS TOWARDS THE PARTY AND SHOUTS, "BEGONE, STRANGERS!" HE THEN BEGINS WAVING HIS HANDS, AND INTONES THE WORDS, "MAPIRO MAHAMA DIROMAT" The fix: Added a delay after the incantation before going back to the castle. Why this fix: Give the player a chance to read the message. Source disk: Wiz1B.dsk File: SPECIALS2.TEXT Procedure: PROCEDURE BCK2SHOP; (* P01031E *) Code from: BEGIN MAZELEV := 0; WRITE( CHR(12)); XGOTO := XNEWMAZE END; Code to: BEGIN PAUSE2; (* WC031 *) MAZELEV := 0; WRITE( CHR(12)); XGOTO := XNEWMAZE END; Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC032 - Roster Out Characters ============================================= Status: Fixed. Recompiled. Verified. Date of change: 06-Mar-2023. Contributors: Eric Labelle, information from Denis Molony. The issue: In the Training Grounds, the Roster of players does not always display characters that are "Out" in the dungeon. Note that characters that are "Out" cannot be added to the party at Gilgamesh's Tavern. The fix: Updated the code to display all characters that are "Out". Why this fix: To display all the characters that are "Out" at the Training Grounds. Now there is an indication as to why a character cannot be added to the party. Source disk: Wiz1C.dsk File: ROLLER.TEXT Procedure: PROCEDURE DSP20NM; (* P010B15 *) Code from: IF CHARREC.INMAZE OR (CHARREC.LOSTXYL.LOCATION[ 1] <> 0) THEN WRITE( ' OUT'); Code to: (* WC032 FROM -LOCATION [ 1]- TO -LOCATION [ 3]- *) IF CHARREC.INMAZE OR (CHARREC.LOSTXYL.LOCATION[ 3] <> 0) THEN WRITE( ' OUT'); Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC033 - Inventory Full Fix ========================================== Status: Fixed. Recompiled. Verified. Date of change: 08-Mar-2023. Contributors: Eric Labelle. The issue: Before the fix, a random character was selected to receive a treasure item. If that character's inventory was full, then the item was lost. This meant you might not have gotten Werdna's amulet upon defeating him for example. The fix: Look at the entire party's inventory for space to receive an item. Display a message when the entire party's inventory is full. Why this fix: To avoid having to continuously micro manage the party's inventory to ensure that there is enough space for treasure drops. Source disk: Wiz1C.dsk File: REWARDS.TEXT Procedure: PROCEDURE ITEMREWD; (* P010D1D *) Code from: BEGIN CHARXXXX := RANDOM MOD PARTYCNT; WHILE CHARACTR[ CHARXXXX].STATUS <> OK DO CHARXXXX := (CHARXXXX + 1) MOD PARTYCNT; IF CHARACTR[ CHARXXXX].POSS.POSSCNT = 8 THEN EXIT( ITEMREWD); (* IF RANDOM CHARACTER IS OK AND HAS 8 POSSESSIONS, THEN EXIT !! *) ... Code to: VAR HASROOM : INTEGER; (* WC033 *) CHARYYYY: INTEGER; (* WC033 *) BEGIN (* BEGIN WC033 *) HASROOM := 0; FOR CHARYYYY := 0 TO PARTYCNT - 1 DO BEGIN IF CHARACTR[ CHARYYYY].POSS.POSSCNT < 8 THEN BEGIN HASROOM := 1; CHARXXXX := CHARYYYY END END; IF HASROOM = 0 THEN BEGIN MVCURSOR( 1, 12); PRINTSTR( 'PARTY INVENTORY FULL !'); MVCURSOR( 1, 13); PRINTSTR( 'TREASURE LOST !'); PAUSE2; EXIT( ITEMREWD) END; (* END WC033 *) ... Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC034 - Search for Item ======================================= Status: Fixed. Recompiled. Verified. Date of change: 11-Mar-2023. Contributors: Eric Labelle. The issue: In the maze, the party enters areas where Wizardry tells a story and then asks you if you want to "Search (Y/N)?". If the party's inventory is full then nothing happens and that leaves the player wondering what is going on. The fix: Added messages to inform the player when the characters’ inventories are full as well as when the characters already have the item they are supposed to get. Why this fix: To inform the player as to what is going on when responding yes to "Search (Y/N)?". Source disk: Wiz1B.dsk File: SPECIALS2.TEXT Function: FUNCTION GOTITEM Code from: BEGIN GOTITEM := FALSE; WITH CHARACTR[ CHARX] DO BEGIN IF POSS.POSSCNT = 8 THEN EXIT( GOTITEM); FOR POSSX := 1 TO POSS.POSSCNT DO IF POSS.POSSESS[ POSSX].EQINDEX = ITEMX THEN EXIT( GOTITEM); CLRRECT( 1, 11, 38, 4); MVCURSOR( 1, 11); PRINTSTR( CHARACTR[ CHARX].NAME); PRINTSTR( ' GOT ITEM'); POSSX := POSS.POSSCNT + 1; POSS.POSSCNT := POSSX; POSS.POSSESS[ POSSX].EQINDEX := ITEMX; POSS.POSSESS[ POSSX].EQUIPED := FALSE; POSS.POSSESS[ POSSX].CURSED := FALSE END; GOTITEM := TRUE END; Code to: BEGIN GOTITEM := FALSE; (* WC034 DISPLAY MESSAGES *) PAUSE1; CLRRECT( 1, 11, 38, 4); MVCURSOR( 1, 12); PRINTSTR( CHARACTR[ CHARX].NAME); WITH CHARACTR[ CHARX] DO BEGIN FOR POSSX := 1 TO POSS.POSSCNT DO IF POSS.POSSESS[ POSSX].EQINDEX = ITEMX THEN BEGIN PRINTSTR( ' ALREADY HAS ONE'); EXIT( GOTITEM) END; IF POSS.POSSCNT = 8 THEN BEGIN PRINTSTR( ' IS FULL'); EXIT( GOTITEM) END; PRINTSTR( ' GOT ITEM'); (* END WC034 *) POSSX := POSS.POSSCNT + 1; POSS.POSSCNT := POSSX; POSS.POSSESS[ POSSX].EQINDEX := ITEMX; POSS.POSSESS[ POSSX].EQUIPED := FALSE; POSS.POSSESS[ POSSX].CURSED := FALSE END; GOTITEM := TRUE END; Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Release #: WC035 - Release 2023-03-17 and fixed a misspelling ================================================================== Status: Fixed. Recompiled. Verified. Date of change: 17-Mar-2023. Contributors: E. Labelle. The result: This if the first complete release of Wizardry Proving Grounds v3.0. Also, fixed a misspelling. The adjustment: Updated the release date on the boot disk. Fixed the misspelling of "Resurrects" when casting Haman or Mahaman. Why this: Bugs and issues fixed. Enhancements done. Ready to distribute. Source disks: Wiz1E.dsk, Wiz1B.dsk Files: OPTIONS.TEXT, COMBAT4.TEXT Code from: WRITE( ' VERSION 3.0 OF 14-FEB-23 SER:'); Code to: WRITE( ' VERSION 3.0 OF 16-MAR-23 SER:'); Code from: PRINTSTR( 'RESSURECTS AND '); Code to: (* WC035 FROM -RESSURECTS- TO -RESURRECTS- *) PRINTSTR( 'RESURRECTS AND '); Final compiled file names: SYSTEM.STARTUP and WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Release #: WC036 - Release 2023-03-23 in alignmentd with a ProDOS release =============================================================================== Status: Fixed. Recompiled. Verified. Date of change: 23-Mar-2023. Contributors: E. Labelle. The result: This a complete release of Wizardry Proving Grounds v3.0. The adjustment: Bypassed a copy protection check halt which is the same fix that was done on the boot side. Added a Q)uit option after leaving the game to really exit the game in order for the ProDOS version to send you back to ProDOS instead of having to reboot. Updated the date. Why this: A released version that accomodates the ProDOS package. Source disk: Wiz1A.dsk File: WIZ.TEXT Program: PROGRAM WIZARDRY; Code from: WRITE( CHR( 12)); GOTOXY( 0, 10); WRITE( ' PRESS [RETURN] FOR MORE WIZARDRY '); READLN Code to: (* WC036 - BEGIN *) WRITE( CHR( 12)); GOTOXY( 4, 10); WRITE( 'PRESS [RETURN] FOR MORE WIZARDRY '); GOTOXY( 12, 13); WRITE( 'OR Q)UIT THE GAME '); REPEAT GETKEY UNTIL (INCHAR = 'Q') OR (INCHAR = CHR( CRETURN)); IF INCHAR = 'Q' THEN BEGIN GOTOXY( 4, 16); WRITE( 'THANK YOU FOR PLAYING WIZARDRY! '); PAUSE2; EXIT( WIZARDRY) END (* WC036 - END *) Source disks: Wiz1B.dsk Files: SPECIALS.TEXT Procedure: PROCEDURE COPYPROT; (* P010310 *) Code from: IF GOODCOPY THEN Code to: (* WC036 REMARKED OUT TO BYPASS COPY PROTECTION FAILURE *) (* IF GOODCOPY THEN *) Source disks: Wiz1E.dsk Files: OPTIONS.TEXT Procedure: SEGMENT PROCEDURE OPTIONS; (* P070301 *) Code from: WRITE( ' VERSION 3.0 OF 17-MA-23 SER:'); Code to: WRITE( ' VERSION 3.0 OF 23-MAR-23 SER:'); Final compiled file names: SYSTEM.STARTUP and WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC037 - Disarm Trap Bug ======================================= Status: Fixed. Recompiled. Verified. Date of change: 03-Apr-2023. Contributors: Eric Labelle. Bug reported by Reiska42. The issue: This happens when finding a chest that is booby trapped with a trap of type 3 (Crossbow Bolt, Exploding Box, Splinters, Blades, and Stunner). Upon disarming the trap if you enter any valid trap name besides the current trap then nothing happens and you go back to the chest options. You can continue entering all the trap names and nothing will happen. The only way out is to open the chest, leave it, or enter the right trap name. The fix: Added the same code as in Wizardry III Legacy of Llylgamyn to fix this bug. Why this fix: To make disarming chest traps work as intended. Source disk: Wiz1C.dsk File: REWARDS.TEXT Procedure: DISARM; (* P010D18 *) Code from: ELSE IF TRAPTYPE = 3 THEN BEGIN CASE TRAP3TYP OF 0: IF TRAPSTR = 'CROSSBOW BOLT' THEN DISARM; 1: IF TRAPSTR = 'EXPLODING BOX' THEN DISARM; 2: IF TRAPSTR = 'SPLINTERS' THEN DISARM; 3: IF TRAPSTR = 'BLADES' THEN DISARM; 4: IF TRAPSTR = 'STUNNER' THEN DISARM; END; END Code to: ELSE IF TRAPTYPE = 3 THEN BEGIN CASE TRAP3TYP OF 0: IF TRAPSTR = 'CROSSBOW BOLT' THEN DISARM; 1: IF TRAPSTR = 'EXPLODING BOX' THEN DISARM; 2: IF TRAPSTR = 'SPLINTERS' THEN DISARM; 3: IF TRAPSTR = 'BLADES' THEN DISARM; 4: IF TRAPSTR = 'STUNNER' THEN DISARM; END; (* WC037 ADDED -DOTRAPDM- AS IN WIZ 3 *) DOTRAPDM END Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Enhancement #: WC038 - Camp Screen Update ========================================== Status: Fixed. Recompiled. Verified. Date of change: 03-Apr-2023. Contributors: Eric Labelle. Enhancement suggested by Reiska42. The suggestion: Update the gold, hit points and status of a character when performing actions such as trading gold, or casting spells to cure hit points or ailments. The action: Added the necessary code to allow these enhancements. Why this: It is nice now to see the screen updated on the fly when performing these actions. Source disk: Wiz1C.dsk File: CAMP.TEXT, CAMP2.TEXT Procedure: PROCEDURE DSPSPELS; (* P010C04 *), PROCEDURE TRADITEM; (* P010C1A *) Code from: BEGIN WITH CHARACTR[ CAMPCHAR] DO BEGIN GOTOXY( 0, 9); WRITE( ' ' : 7); WRITE( ' MAGE '); FOR INDX := 1 TO 7 DO BEGIN WRITE( MAGESP[ INDX]); IF INDX < 7 THEN WRITE( '/') END; WRITELN; WRITE( ' ' :6); WRITE( 'PRIEST '); FOR INDX := 1 TO 7 DO BEGIN WRITE( PRIESTSP[ INDX]); IF INDX < 7 THEN WRITE( '/') END END END; Code to: BEGIN WITH CHARACTR[ CAMPCHAR] DO BEGIN (* WC038 - BEGIN *) GOTOXY( 24, 2); PRNTLONG( GOLD); GOTOXY( 24, 6); WRITE( HPLEFT :3); GOTOXY( 24, 7); WRITE( SCNTOC.STATUS[ STATUS]); IF LOSTXYL.POISNAMT[ 1] > 0 THEN WRITE( ' & POISONED') ELSE WRITE( ' '); (* WC038 - END *) GOTOXY( 0, 9); WRITE( ' ' : 7); WRITE( ' MAGE '); FOR INDX := 1 TO 7 DO BEGIN WRITE( MAGESP[ INDX]); IF INDX < 7 THEN WRITE( '/') END; WRITELN; WRITE( ' ' :6); WRITE( 'PRIEST '); FOR INDX := 1 TO 7 DO BEGIN WRITE( PRIESTSP[ INDX]); IF INDX < 7 THEN WRITE( '/') END END END; (* WC037 ADDED -DOTRAPDM- AS IN WIZ 3 *) DOTRAPDM END Code from: BEGIN (* DOTRADE *) DISPSTAT := FALSE; REPEAT TRADETO := GETCHARX( TRUE, 'TRADE WITH'); IF TRADETO = -1 THEN EXIT( DOTRADE); UNTIL TRADETO <> CAMPCHAR; TRADGOLD; TRADITEM END; (* DOTRADE *) Code to: BEGIN (* DOTRADE *) DISPSTAT := FALSE; REPEAT TRADETO := GETCHARX( TRUE, 'TRADE WITH'); IF TRADETO = -1 THEN EXIT( DOTRADE); UNTIL TRADETO <> CAMPCHAR; TRADGOLD; DSPSPELS; (* WC038 - TO UPDATE GOLD AMOUNT *) TRADITEM END; (* DOTRADE *) Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Release #: WC039 - Release 09 Apr 2023 and Fix Maze Text Entry Overflow Crash ================================================================================== Status: Fixed. Recompiled. Verified. Date of change: 09-Apr-2023. Contributors: Eric Labelle. Bug reported by Reiska42. The issue: In the maze, when entering text for a spell name, chest trap name, time delay, or answer to a riddle, if you continue typing characters the text will overflow to next lines and eventually the game will crash. The fix: Restrict the length of the entry to the minimum necessary to prevent the game from crashing. Why this fix: To prevent the game from crashing. But did not make it so short as to prevent answering a fairly long riddle of up to 22 characters. One can still corrupt the screen by overtyping but at least the game will not crash anymore. Source disk: Wiz1A.dsk File: WIZ2.TEXT Procedure: PROCEDURE GETSTR; Code from: IF (INCHAR <> CHR( CRETURN)) AND (ORD( INCHAR) >= 32) THEN BEGIN MVCURSOR( WINXPOS + IPOS, WINYPOS); PRINTCHR( INCHAR); IPOS := IPOS + 1; ASTRING[ IPOS] := INCHAR END Code to: IF (INCHAR <> CHR( CRETURN)) AND (ORD( INCHAR) >= 32) THEN BEGIN MVCURSOR( WINXPOS + IPOS, WINYPOS); PRINTCHR( INCHAR); (* WC039 ADDED -IF IPOS < 22 THEN- TO PREVENT A GAME *) (* CRASH WHEN ENTERING TOO LONG A SPELL NAME IN COMBAT. *) (* ALSO APPLIES TO ANSWERS TO RIDDLES, CHEST TRAPS, *) (* AND ENTERING THE TIME DELAY *) IF IPOS < 22 THEN IPOS := IPOS + 1; ASTRING[ IPOS] := INCHAR END Source disks: Wiz1E.dsk Files: OPTIONS.TEXT Procedure: SEGMENT PROCEDURE OPTIONS; (* P070301 *) Code from: WRITE( ' VERSION 3.0 OF 23-MAR-23 SER:'); Code to: WRITE( ' VERSION 3.0 OF 09-APR-23 SER:'); Final compiled file name: WIZARDRY.CODE Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Release #: WC040 - Release 03 Aug 2023 - Pool and Divide Gold and More =========================================================================== Status: Fixed. Recompiled. Verified. Date of change: 03-Aug-2023. Contributors: Eric Labelle. Thomas Ewers (Fix for Make Scenario bug). Thanks: Marshall Bockrath (Tips on Pascal segments sizes, it helped me to figure out where I could cram in the extra code for the Pool/Divide Gold enhancements). Todd Borax (Evil Shield +3 report). Chris Torrence (Transfer characters report). Enhancements: Added the possibility for a character to "Pool the Gold" of the entire party in his pocket. This can be done in Gilgamesh's, Boltac's, Adventurer's Inn and Camp. Furthermore, you can also "Divide the Gold" between all characters whilst inspecting your character at Gilgamesh's or Camp. Enhancements: Updated the code to allow characters to be transferred between scenario disks even if they are carrying quest items. Fix: On the boot side of Wizardry, there is a Utility to "Make Scenario Disk". An off-by-one error in the code had the top half part of the first monster picture overwritten with junk when making the scenario disk. Consistency: The Evil Shield +3 armor class has been improved from 5 to 6 to be consistent with the armor protection of all the other shields. Following are the programming code details ========================================== Enhancement: Pool and Divide Gold ------------------------------------ Source disk: Wiz1A.dsk File: WIZ.TEXT Procedure: PROCEDURE POOLALLG Code from: (* ---------- BEGIN FORWARD DECLARATIONS ---------- *) Code to: (* ---------- BEGIN FORWARD DECLARATIONS ---------- *) PROCEDURE POOLALLG( CHAR4GLD: INTEGER); FORWARD; (* WC040 POOL GOLD *) Source disk: Wiz1A.dsk File: WIZ2.TEXT Procedure: PROCEDURE POOLALLG; (* WC040 POOL GOLD *) Code from: N/A. Code to: PROCEDURE POOLALLG; (* WC040 POOL GOLD *) VAR ALOOP4 : INTEGER; BEGIN FOR ALOOP4 := 0 TO PARTYCNT -1 DO IF ALOOP4 <> CHAR4GLD THEN BEGIN WITH CHARACTR[ ALOOP4].GOLD DO BEGIN ADDLONGS( CHARACTR[ CHAR4GLD].GOLD, CHARACTR[ ALOOP4].GOLD); HIGH := 0; MID := 0; LOW := 0 END END END; Source disk: Wiz1C.dsk File: CAMP2.TEXT Procedure: PROCEDURE CAMPDO; (* P010C1B *) Code from: BEGIN (* CAMPMENU *) WITH CHARACTR[ CAMPCHAR] DO BEGIN IF DISPSTAT THEN DSPSTATS; GOTOXY( 0, 18); IF XGOTO = XINSPCT3 THEN MENUTYPE := 0 ELSE IF XGOTO = XINSPECT THEN MENUTYPE := 1 ELSE IF STATUS = OK THEN MENUTYPE := 2 ELSE MENUTYPE := 1; IF MENUTYPE = 2 THEN BEGIN WRITE( CHR( 11)); WRITELN( 'YOU MAY E)QUIP, D)ROP AN ITEM, T)RADE,'); WRITE( ' ' :8); WRITELN( 'R)EAD SPELL BOOKS, CAST S)PELLS,'); WRITE( ' ' :8); WRITELN( 'U)SE AN ITEM, I)DENTIFY AN ITEM,'); WRITE( ' ' :8); WRITELN( 'OR L)EAVE.') END ELSE IF MENUTYPE = 1 THEN BEGIN WRITE( CHR( 11)); WRITELN( 'YOU MAY E)QUIP, D)ROP AN ITEM, T)RADE,'); WRITE( ' ' :8); WRITELN( 'R)EAD SPELL BOOKS, OR L)EAVE.') END ELSE BEGIN WRITE( CHR( 11)); WRITELN( 'YOU MAY R)EAD SPELL BOOKS OR L)EAVE.') END; END END; (* CAMPMENU *) BEGIN (* CAMPDO *) CAMPMENU; DISPSTAT := TRUE; REPEAT GOTOXY( 41, 0); GETKEY UNTIL (INCHAR = 'R') OR (INCHAR = 'L') OR ((MENUTYPE > 0) AND ((INCHAR = 'T') OR (INCHAR = 'D') OR (INCHAR = 'E'))) OR ((MENUTYPE > 1) AND ((INCHAR = 'I') OR (INCHAR = 'S') OR (INCHAR = 'U'))); CASE INCHAR OF 'L': EXIT( CAMPDO); 'E': IF MENUTYPE > 0 THEN BEGIN XGOTO := XEQPDSP; LLBASE04 := CAMPCHAR; EXIT( CAMP) END; 'R': BEGIN XGOTO := XCAMPSTF; BASE12.GOTOX := XDONE; LLBASE04 := CAMPCHAR; EXIT( CAMP) END; 'D': IF MENUTYPE > 0 THEN DROPITEM; 'I': IF MENUTYPE = 2 THEN IDENTIFY; 'S': IF MENUTYPE = 2 THEN CASTSPEL( -1); 'U': IF MENUTYPE = 2 THEN USEITEM; 'T': DOTRADE END END; (* CAMPDO *) Code to: PROCEDURE MENULST4; (* WC040 *) BEGIN WRITE( CHR( 11)); WRITELN( 'YOU MAY E)QUIP, D)ROP AN ITEM, T)RADE,'); WRITE( ' ' :8); WRITELN( 'POOL G)OLD, DIV)IDE GOLD,'); WRITE( ' ' :8); END; PROCEDURE MENULST5; (* WC040 *) BEGIN WRITELN( 'R)EAD SPELL BOOKS, OR L)EAVE.') END; BEGIN (* CAMPMENU *) WITH CHARACTR[ CAMPCHAR] DO BEGIN IF DISPSTAT THEN DSPSTATS; GOTOXY( 0, 18); IF XGOTO = XINSPCT3 THEN MENUTYPE := 0 ELSE IF XGOTO = XINSPECT THEN MENUTYPE := 1 ELSE IF STATUS = OK THEN MENUTYPE := 2 ELSE MENUTYPE := 1; IF MENUTYPE = 2 THEN BEGIN MENULST4; (* WC040 *) WRITELN( 'U)SE AN ITEM, I)DENTIFY AN ITEM,'); WRITE( ' ' :8); WRITELN( 'CAST S)PELLS,'); WRITE( ' ' :8); MENULST5 (* WC040 *) END ELSE IF MENUTYPE = 1 THEN BEGIN MENULST4; (* WC040 *) MENULST5 (* WC040 *) END ELSE BEGIN WRITE( CHR( 11)); WRITE( 'YOU MAY '); MENULST5 (* WC040 *) END; END END; (* CAMPMENU *) PROCEDURE DIVALLG( CHAR4GLD: INTEGER); (* WC040 *) VAR ALOOP4 : INTEGER; GOLD2DIV : TWIZLONG; GOLDLESS : TWIZLONG; BEGIN POOLALLG( CHAR4GLD); GOLD2DIV := CHARACTR[ CHAR4GLD].GOLD; DIVLONG( GOLD2DIV, PARTYCNT); GOLDLESS := GOLD2DIV; MULTLONG( GOLDLESS, PARTYCNT); SUBLONGS( CHARACTR[ CHAR4GLD].GOLD, GOLDLESS); FOR ALOOP4 := 0 TO PARTYCNT - 1 DO ADDLONGS( CHARACTR[ ALOOP4].GOLD, GOLD2DIV) END; BEGIN (* CAMPDO *) CAMPMENU; DISPSTAT := TRUE; REPEAT GOTOXY( 41, 0); GETKEY UNTIL (INCHAR = 'R') OR (INCHAR = 'L') OR ((MENUTYPE > 0) AND ((INCHAR = 'T') OR (INCHAR = 'D') OR (INCHAR = 'E') OR (INCHAR = 'G') OR (INCHAR = 'V'))) OR ((MENUTYPE > 1) AND ((INCHAR = 'I') OR (INCHAR = 'S') OR (INCHAR = 'U'))); CASE INCHAR OF 'L': EXIT( CAMPDO); 'E': IF MENUTYPE > 0 THEN BEGIN XGOTO := XEQPDSP; LLBASE04 := CAMPCHAR; EXIT( CAMP) END; 'R': BEGIN XGOTO := XCAMPSTF; BASE12.GOTOX := XDONE; LLBASE04 := CAMPCHAR; EXIT( CAMP) END; 'D': IF MENUTYPE > 0 THEN DROPITEM; 'G': IF MENUTYPE > 0 THEN POOLALLG( CAMPCHAR); (* WC040 POOL GOLD *) 'V': IF MENUTYPE > 0 THEN DIVALLG( CAMPCHAR); (* WC040 DIVIDE GOLD *) 'I': IF MENUTYPE = 2 THEN IDENTIFY; 'S': IF MENUTYPE = 2 THEN CASTSPEL( -1); 'U': IF MENUTYPE = 2 THEN USEITEM; 'T': DOTRADE END END; (* CAMPDO *) Source disk: Wiz1C.dsk File: CASTLE2.TEXT Procedures: PROCEDURE ADVNTINN; (* P010A0F *) PROCEDURE INNMENU; (* P010A11 *) Code from: PROCEDURE ADVNTINN; (* P010A0F *) CONST STABLES = 65; COTS = 66; ECONOMY = 67; MERCHANT = 68; ROYAL = 69; . . . PROCEDURE INNMENU; (* P010A11 *) BEGIN GOTOXY( 0, 13); WRITE( CHR( 11)); WRITE( ' WELCOME '); WRITE( CHARACTR[ PARTYX].NAME); WRITELN( '. WE HAVE:'); WRITELN; WRITELN( '[A] THE STABLES (FREE!)'); WRITELN( '[B] COTS. 10 GP/WEEK.'); WRITELN( '[C] ECONOMY ROOMS. 50 GP/WEEK.'); WRITELN( '[D] MERCHANT SUITES. 200 GP/WEEK.'); WRITELN( '[E] ROYAL SUITES. 500 GP/WEEK.'); WRITE( ' OR [RETURN] TO LEAVE') END; . . . BEGIN (* ADVNTINN *) REPEAT GETWHO; IF CHARACTR[ PARTYX].STATUS = OK THEN REPEAT UNITCLEAR( 1); INNMENU; GOTOXY( 41, 0); GETKEY; CASE ORD( INCHAR) OF STABLES: TAKENAP( 0, 0); COTS: TAKENAP( 1, 10); ECONOMY: TAKENAP( 3, 50); MERCHANT: TAKENAP( 7, 200); ROYAL: TAKENAP( 10, 500); END; CHARINFO( PARTYX) UNTIL (INCHAR = CHR( CRETURN)) OR (CHARACTR[ PARTYX].STATUS <> OK) UNTIL FALSE END; (* ADVNTINN *) Code to: PROCEDURE ADVNTINN; (* P010A0F *) CONST STABLES = 65; COTS = 66; ECONOMY = 67; MERCHANT = 68; ROYAL = 69; PGOLD = 71; (* WC040 *) . . . PROCEDURE INNMENU; (* P010A11 *) BEGIN GOTOXY( 0, 13); WRITE( CHR( 11)); WRITE( ' WELCOME '); WRITE( CHARACTR[ PARTYX].NAME); WRITELN( '. WE HAVE:'); WRITELN; WRITELN( '[A] THE STABLES (FREE!)'); WRITELN( '[B] COTS. 10 GP/WEEK.'); WRITELN( '[C] ECONOMY ROOMS. 50 GP/WEEK.'); WRITELN( '[D] MERCHANT SUITES. 200 GP/WEEK.'); WRITELN( '[E] ROYAL SUITES. 500 GP/WEEK.'); WRITELN; WRITELN( '[G] POOL PARTY GOLD.'); (* WC040 *) WRITELN; WRITE( ' OR [RETURN] TO LEAVE') END; . . . BEGIN (* ADVNTINN *) REPEAT GETWHO; IF CHARACTR[ PARTYX].STATUS = OK THEN REPEAT UNITCLEAR( 1); INNMENU; GOTOXY( 41, 0); GETKEY; CASE ORD( INCHAR) OF STABLES: TAKENAP( 0, 0); COTS: TAKENAP( 1, 10); ECONOMY: TAKENAP( 3, 50); MERCHANT: TAKENAP( 7, 200); ROYAL: TAKENAP( 10, 500); PGOLD: POOLALLG( PARTYX); (* WC040 *) END; CHARINFO( PARTYX) UNTIL (INCHAR = CHR( CRETURN)) OR (CHARACTR[ PARTYX].STATUS <> OK) UNTIL FALSE END; (* ADVNTINN *) Source disk: Wiz1B.dsk File: SHOPS.TEXT Procedure: PROCEDURE DOPLAYER; (* P01020B *) Code from: BEGIN (* DOPLAYER *) REPEAT GOTOXY( 0, 13); WRITE( CHR( 11)); WRITE( ' WELCOME '); WRITE( CHARACTR[ CHARI].NAME); WRITELN; WRITE( ' YOU HAVE '); PRNTLONG( CHARACTR[ CHARI].GOLD); WRITELN( ' GOLD'); WRITELN; WRITELN( 'YOU MAY B)UY AN ITEM,'); WRITELN( ' S)ELL AN ITEM, HAVE AN ITEM'); WRITELN( ' U)NCURSED, OR HAVE AN ITEM'); WRITELN( ' I)DENTIFIED, OR L)EAVE'); GOTOXY( 41, 0); GETKEY; CASE INCHAR OF 'U': SELLIDUN( UNCURSE); 'I': SELLIDUN( IDENTIFY); 'S': SELLIDUN( SELL); 'B': DOBUY; 'L': EXIT( DOPLAYER); END UNTIL FALSE END; (* DOPLAYER *) Code to: BEGIN (* DOPLAYER *) REPEAT GOTOXY( 0, 13); WRITE( CHR( 11)); WRITE( ' WELCOME '); WRITE( CHARACTR[ CHARI].NAME); WRITELN; WRITE( ' YOU HAVE '); PRNTLONG( CHARACTR[ CHARI].GOLD); WRITELN( ' GOLD'); WRITELN; WRITELN( 'YOU MAY POOL G)OLD, B)UY AN ITEM,'); (* WC040 *) WRITELN( ' S)ELL AN ITEM, HAVE AN ITEM'); WRITELN( ' U)NCURSED, OR HAVE AN ITEM'); WRITELN( ' I)DENTIFIED, OR L)EAVE'); GOTOXY( 41, 0); GETKEY; CASE INCHAR OF 'G': POOLALLG( CHARI); (* WC040 *) 'U': SELLIDUN( UNCURSE); 'I': SELLIDUN( IDENTIFY); 'S': SELLIDUN( SELL); 'B': DOBUY; 'L': EXIT( DOPLAYER); END UNTIL FALSE END; (* DOPLAYER *) Enhancement: Allow characters to be transferred between scenario disks even if they are carrying quest items. ------------------------------------ Source disk: Wiz1E.dsk File: WIZUTILC.TEXT Procedure: PROCEDURE REMOVCHR; (* P070118 *) Code from: The code below has been remarked out. Code to: (* WC040 REMARKED OUT TO ALLOW TRANSFER OF QUEST ITEMS *) (* PROCEDURE BADITEM; *) (* P070119 *) (* BEGIN WRITELN; WRITELN( '** CHAR HAS NON-XFERRABLE ITEMS **'); PRESSRET; EXIT( TRANSFER) END; *) . . . (* WC040 REMARKED OUT TO ALLOW TRANSFER OF QUEST ITEMS *) (* FOR PLAYERI := 1 TO PLAYREC2.POSS.POSSCNT DO IF PLAYREC2.POSS.POSSESS[ PLAYERI].EQINDEX > 93 THEN BADITEM; *) Fix: On the boot side of Wizardry, there is a Utility to "Make Scenario Disk". An off-by-one error in the code had the top half part of the first monster picture overwritten with junk when making the scenario disk. ------------------------------------ Source disk: Wiz1E.dsk File: WIZUTILC.TEXT Procedure: PROCEDURE MAKESCEN; (* P07011C *) Code from: FOR TEMPI := 0 TO SCNTOC.RECPERDK[ ZCHAR] DO WRCHARAC( CHARREC0, TEMPI); Code to: (* WC040 FROM 'SCNTOC.RECPERDK[ ZCHAR]' TO 'SCNTOC.RECPERDK[ ZCHAR] - 1' *) (* THIS ERROR BY 1 WAS OVERWRITING PART OF THE FIRST MONSTER PICTURE *) FOR TEMPI := 0 TO SCNTOC.RECPERDK[ ZCHAR] - 1 DO WRCHARAC( CHARREC0, TEMPI); Update: Database Update ------------------------------- Source disks: Scenario Disk Files: SCENARIO.DATA From: Evil Shield +3 armor class 5 To: Evil Shield +3 armor class 6 Update: Release Date ---------------------------- Source disks: Wiz1E.dsk Files: OPTIONS.TEXT Procedure: SEGMENT PROCEDURE OPTIONS; (* P070301 *) Code from: (* ST001 CHANGE VERSION AND DATE DISPLAY AS NEEDED *) WRITE( ' VERSION 3.0 OF 09-APR-23 SER:'); WRITELN( SERIAL); Code to: (* ST001 CHANGE VERSION AND DATE DISPLAY AS NEEDED *) WRITE( ' VERSION 3.0 OF 03-AUG-23 SER:'); WRITELN( SERIAL); Final compiled file names: WIZARDRY.CODE, SYSTEM.STARTUP Destination disks: Any Wizardry Proving Grounds boot and scenario disks. Enhancement #: WC041 - Do not transfer quest items - Show full 4-digits year on splash screen ============================================================================================== Status: Fixed. Recompiled. Verified. Date of change: 05-Feb-2024. Contributors: Eric Labelle. Enhancements: Revert the code done in WC040 to disallow characters to be transferred between scenario disks when they are carrying quest items. Information: This was done in WC040 to facilitate transferring characters between Proving Grounds and other alternate PG scenarios. But that has potential undesireable effets upon the transfer to the Knight of Diamonds scenario when using the transfer utility from the PG boot disk instead of the KOD boot disk. Enhancements: On spash screen upon boot show 4 digits for date year instead of 2 digits. Following are the programming code details ========================================== Enhancement: Revert - Allow characters to be transferred between scenario disks even if they are carrying quest items. ------------------------------------------ Source disk: Wiz1E.dsk File: WIZUTILC.TEXT Procedure: PROCEDURE REMOVCHR; (* P070118 *) Code from: The code below was remarked out. (* WC040 REMARKED OUT TO ALLOW TRANSFER OF QUEST ITEMS *) (* PROCEDURE BADITEM; *) (* P070119 *) (* BEGIN WRITELN; WRITELN( '** CHAR HAS NON-XFERRABLE ITEMS **'); PRESSRET; EXIT( TRANSFER) END; *) . . . (* WC040 REMARKED OUT TO ALLOW TRANSFER OF QUEST ITEMS *) (* FOR PLAYERI := 1 TO PLAYREC2.POSS.POSSCNT DO IF PLAYREC2.POSS.POSSESS[ PLAYERI].EQINDEX > 93 THEN BADITEM; *) Code to: PROCEDURE BADITEM; (* P070119 *) BEGIN WRITELN; WRITELN( '** CHAR HAS NON-XFERRABLE ITEMS **'); PRESSRET; EXIT( TRANSFER) END; . . . FOR PLAYERI := 1 TO PLAYREC2.POSS.POSSCNT DO IF PLAYREC2.POSS.POSSESS[ PLAYERI].EQINDEX > 93 THEN BADITEM; Enhancements: On spash screen upon boot show 4 digits for date year instead of 2 digits. ------------------------------------------ Source disks: Wiz1E.dsk Files: OPTIONS.TEXT Procedure: SEGMENT PROCEDURE OPTIONS; (* P070301 *) Code from: (* ST001 CHANGE VERSION AND DATE DISPLAY AS NEEDED *) WRITE( ' VERSION 3.0 OF 09-APR-23 SER:'); WRITELN( SERIAL); Code to: (* ST001 CHANGE VERSION AND DATE DISPLAY AS NEEDED *) WRITE( ' VERSION 3.0 OF 05-FEB-2024 SER:'); WRITELN( SERIAL); Final compiled file names: SYSTEM.STARTUP Destination disks: Any Wizardry Proving Grounds boot disks. Release #: WC042 - Release 08 Feb 2024 - Allow transfer characters to any scenario copy - Correct spelling =============================================================================================================== Status: Fixed. Recompiled. Verified. Date of change: 08-Feb-2024. Contributors: Eric Labelle. Enhancements: Added the possibility transfer characters to any scenario copy even if it has the same serial number as the source. Spelling: Full spelling and corrected double "R" from "** CHAR HAS NON-XFERRABLE ITEMS **" to "** CHAR HAS NON-TRANSFERABLE ITEMS **". Following are the programming code details ========================================== Enhancement: Transfer characters to any scenario copy even if it has the same serial number as the source ------------------------------------ Source disk: Wiz1E.dsk File: WIZUTILC.TEXT Procedure: PROCEDURE TRANSFER; (* P070117 *) PROCEDURE TRANBAD; (* P07011A *) Code from: PROCEDURE TRANBAD; (* P07011A *) BEGIN REPEAT REPEAT IF (MPD3 = BL5BUFF[ 10]) AND (SERIALFR = SERIALTO) THEN RDSCNTOC( 'CANT COPY TO BACKUP - PUT IN SOURCE') ELSE IF (PLAYINDX = -1) THEN RDSCNTOC( 'DUPLICATE NAME - PUT IN SOURCE') ELSE RDSCNTOC( 'ALL SLOTS USED - PUT IN SOURCE'); . . . BEGIN (* TRANSFER *) . . . IF (MPD3 <> BL5BUFF[ 10]) OR (SERIALFR <> SERIALTO) THEN BEGIN . . . END; Code to: PROCEDURE TRANBAD; (* P07011A *) BEGIN REPEAT REPEAT (* WC042 DISABLE SERIAL NUMBER CHECK TO ALLOW MOVING CHARACTERS TO ANY SCENARIO COPY *) (* IF (MPD3 = BL5BUFF[ 10]) AND (SERIALFR = SERIALTO) THEN RDSCNTOC( 'CANT COPY TO BACKUP - PUT IN SOURCE') ELSE *) IF (PLAYINDX = -1) THEN RDSCNTOC( 'DUPLICATE NAME - PUT IN SOURCE') ELSE RDSCNTOC( 'ALL SLOTS USED - PUT IN SOURCE'); . . . BEGIN (* TRANSFER *) . . . (* WC042 DISABLE SERIAL NUMBER CHECK TO ALLOW MOVING CHARACTERS TO ANY SCENARIO COPY *) (* IF (MPD3 <> BL5BUFF[ 10]) OR (SERIALFR <> SERIALTO) THEN BEGIN *) . . . (* END; *) (* WC042 *) Enhancement: Corrected double "R" from "** CHAR HAS NON-XFERRABLE ITEMS **" to "** CHAR HAS NON-TRANSFERABLE ITEMS **" ------------------------------------ Source disk: Wiz1E.dsk File: WIZUTILC.TEXT Procedure: PROCEDURE BADITEM; (* P070119 *) Code from: BEGIN WRITELN; WRITELN( '** CHAR HAS NON-X-FERRABLE ITEMS **'); PRESSRET; EXIT( TRANSFER) END; Code to: BEGIN WRITELN; (* WC042 FROM NON-XFERRABLE TO NON-TRANSFERABLE *) WRITELN( '** CHAR HAS NON-TRANSFERABLE ITEMS **'); PRESSRET; EXIT( TRANSFER) END; Update: Release Date ---------------------------- Source disks: Wiz1E.dsk Files: OPTIONS.TEXT Procedure: SEGMENT PROCEDURE OPTIONS; (* P070301 *) Code from: (* ST001 CHANGE VERSION AND DATE DISPLAY AS NEEDED *) WRITE( ' VERSION 3.0 OF 03-AUG-23 SER:'); WRITELN( SERIAL); Code to: (* ST001 CHANGE VERSION AND DATE DISPLAY AS NEEDED *) (* WC041 SHOW FULL 4 DIGITS YEAR DATE *) WRITE( ' VERSION 3.0 OF 08-FEB-2024 SER:'); WRITELN( SERIAL); Final compiled file names: SYSTEM.STARTUP Destination disk: Any Wizardry Proving Grounds boot disk. Enhancement #: WC043 - Kandi spell enhancements ================================================ Status: Fixed. Recompiled. Verified. Date of change: 20-Mar-2024. Contributors: Eric Labelle. Enhancements: The Kandi spell (find character location) now gives the precise location of a dead character in the maze instead of just the general area. Furthermore, Kandi now gives the character's camp location in the maze when using the D)isband option. Note: This reduces the Kandi spell programming space and thus its Pascal coding segment size sufficiently to cross a block in downsize thus giving almost an entire 512 bytes of extra coding space for future enhancements coming after this one. Following are the programming code details ========================================== Source disk: Wiz1C.dsk File: UTILITIE.TEXT Procedure: PROCEDURE KANDILOC; (* P01010C *) Code from: BEGIN IF LOSTCHAR.STATUS = LOST THEN EXIT( KANDILOC); IF LOSTCHAR.STATUS < DEAD THEN WRITELN( 'STILL WITH US!') ELSE BEGIN IF (LOSTCHAR.LOSTXYL.LOCATION[ 1] = 0) AND (LOSTCHAR.LOSTXYL.LOCATION[ 2] = 0) AND (LOSTCHAR.LOSTXYL.LOCATION[ 3] = 0) THEN WRITELN( 'IN THE MOURGE') ELSE IF LOSTCHAR.LOSTXYL.LOCATION[ 3] <= 0 THEN BEGIN WRITELN( 'UNREACHABLE!') END ELSE BEGIN WRITE( 'IN THE '); IF LOSTCHAR.LOSTXYL.LOCATION[ 2] > 9 THEN WRITE( 'NORTH ') ELSE WRITE( 'SOUTH '); IF LOSTCHAR.LOSTXYL.LOCATION[ 1] > 9 THEN WRITE( 'EAST') ELSE WRITE( 'WEST'); WRITE( ' OF LEVEL '); WRITELN( LOSTCHAR.LOSTXYL.LOCATION[ 3]); END END; EXITKAND END; (* KANDILOC *) Code to: (* BEGIN ENHANCEMENTS WC043 *) BEGIN IF (LOSTCHAR.STATUS = LOST) THEN EXIT( KANDILOC); IF LOSTCHAR.STATUS >= DEAD THEN IF (LOSTCHAR.LOSTXYL.LOCATION[ 3] = 0) THEN BEGIN (* WC002 CHANGE -MOURGE- TO -MORGUE- *) WRITELN( 'IN THE MORGUE'); EXITKAND END; IF (LOSTCHAR.LOSTXYL.LOCATION[ 3] = 0) THEN WRITELN( 'STILL WITH US!'); IF (LOSTCHAR.LOSTXYL.LOCATION[ 3] > 0) THEN BEGIN WRITE( 'AT EAST '); WRITE( LOSTCHAR.LOSTXYL.LOCATION[ 1]); WRITE( ', NORTH '); WRITE( LOSTCHAR.LOSTXYL.LOCATION[ 2]); WRITE( ' OF LEVEL '); WRITELN( LOSTCHAR.LOSTXYL.LOCATION[ 3]) END; (* END ENHANCEMENTS WC043 *) EXITKAND END; (* KANDILOC *) Final compiled file names: WIZARDRY.CODE Destination disk: Any Wizardry Proving Grounds boot and scenario disks. Enhancement #: WC044 - Display Silenced Character Status ========================================================= Status: Fixed. Recompiled. Verified. Date of change: 21-Mar-2024. Contributors: Eric Labelle. Enhancements: Added the status 'SILENC' in the character's status screen in combat when they have been silenced by monsters casting the Montino spell. Following are the programming code details ========================================== Source disk: Wiz1B.dsk File: COMBAT3.TEXT Procedure: PROCEDURE PRSTATUS; (* P010627 *) Code from: BEGIN STATUSOK := STATUSOK OR (CHARACTR[ PARTYI].STATUS < DEAD); IF CHARACTR[ PARTYI].STATUS = OK THEN IF CHARACTR[ PARTYI].LOSTXYL.POISNAMT[ 1] > 0 THEN PRINTSTR( 'POISON') ELSE PRINTNUM( CHARACTR[ PARTYI].HPMAX, 4) ELSE PRINTSTR( SCNTOC.STATUS[ CHARACTR[ PARTYI].STATUS]) END; (* PRSTATUS *) Code to: BEGIN STATUSOK := STATUSOK OR (CHARACTR[ PARTYI].STATUS < DEAD); IF CHARACTR[ PARTYI].STATUS = OK THEN (* WC044 DISPLAY SILENCED CHARACTERS *) IF BATTLERC[ 0].A.TEMP04[ PARTYI].INAUDCNT > 0 THEN PRINTSTR( 'SILENC') ELSE IF CHARACTR[ PARTYI].LOSTXYL.POISNAMT[ 1] > 0 THEN PRINTSTR( 'POISON') ELSE PRINTNUM( CHARACTR[ PARTYI].HPMAX, 4) ELSE PRINTSTR( SCNTOC.STATUS[ CHARACTR[ PARTYI].STATUS]) END; (* PRSTATUS *) Final compiled file names: WIZARDRY.CODE Destination disk: Any Wizardry Proving Grounds boot and scenario disks. Enhancement #: WC045 - Auto Update Hit Points of Poisoned Characters ===================================================================== Status: Fixed. Recompiled. Verified. Date of change: 22-Mar-2024. Contributors: Eric Labelle. Enhancements: Added code to automatically update the remaining hit points of poisoned characters in the status window while walking in the maze. Following are the programming code details ========================================== Source disk: Wiz1C.dsk File: RUNNER2.TEXT Procedure: PROCEDURE UPDATEHP; (* P010E1C *) Code from: VAR UNUSEDXX : INTEGER; CHARX : INTEGER; BEGIN FOR CHARX := 0 TO PARTYCNT - 1 DO WITH CHARACTR[ CHARX] DO BEGIN IF (RANDOM MOD 4) = 2 THEN HPLEFT := HPLEFT - LOSTXYL.POISNAMT[ 1] + HEALPTS; IF HPLEFT <= 0 THEN BEGIN LOSTXYL.POISNAMT[ 1] := 0; IF STATUS < DEAD THEN BEGIN MVCURSOR( 1, 11); PRINTSTR( NAME); PRINTSTR( ' DIED'); PAUSE2; CLRRECT( 1, 11, 38, 1); HPLEFT := 0; STATUS := DEAD; PRSTATS END END ELSE IF HPLEFT > HPMAX THEN HPLEFT := HPMAX END END; (* UPDATEHP *) Code to: VAR UNUSEDXX : INTEGER; CHARX : INTEGER; SHOWPOIS : INTEGER; BEGIN SHOWPOIS := 0; FOR CHARX := 0 TO PARTYCNT - 1 DO WITH CHARACTR[ CHARX] DO BEGIN IF (RANDOM MOD 4) = 2 THEN HPLEFT := HPLEFT - LOSTXYL.POISNAMT[ 1] + HEALPTS; IF HPLEFT <= 0 THEN BEGIN LOSTXYL.POISNAMT[ 1] := 0; IF STATUS < DEAD THEN BEGIN MVCURSOR( 1, 11); PRINTSTR( NAME); PRINTSTR( ' DIED'); PAUSE2; CLRRECT( 1, 11, 38, 1); HPLEFT := 0; STATUS := DEAD; PRSTATS END END ELSE IF HPLEFT > HPMAX THEN HPLEFT := HPMAX; (* WC045 REFRESH STATS AUTOMATICALLY WHEN POISONED *) IF LOSTXYL.POISNAMT[ 1] > 0 THEN SHOWPOIS := 1 END; IF SHOWPOIS = 1 THEN PRSTATS END; (* UPDATEHP *) Final compiled file names: WIZARDRY.CODE Destination disk: Any Wizardry Proving Grounds boot and scenario disks. Enhancement #: WC046 - Monsters cannot yell for help when surprised ==================================================================== Status: Fixed. Recompiled. Verified. Date of change: 23-Mar-2024. Contributors: Eric Labelle. Enhancements: Prevent monsters from yelling for help when surprised. This was a guaranteed party slaughter (game breaker) in many scenarios. For Proving Grounds for example, on level 10, if four Dragon Zombies surprised you, you could end up facing eight Dragon Zombies the next round, no party can survive this. And if there are multiple groups of monsters surprising you it was even worse. Following are the programming code details ========================================== Source disk: Wiz1B.dsk File: COMBAT2.TEXT Procedure: PROCEDURE ENATTACK; (* P010614 *) Code from: IF ATTCKTYP = 0 THEN YELLHELP; Code to: IF SURPRISE = 0 THEN IF ATTCKTYP = 0 THEN YELLHELP; (* WC046 *) Final compiled file names: WIZARDRY.CODE Destination disk: Any Wizardry Proving Grounds boot and scenario disks. Release #: WC047 - Release 24 March 2024 v3.1 ================================================== Status: Fixed. Recompiled. Verified. Date of change: 24-Mar-2024. Contributors: Eric Labelle. Enhancements: Fully recompiled release v3.1 as of 24 March 2024. Following are the programming code details ========================================== Source disk: Wiz1E.dsk File: OPTIONS.TEXT Procedure: SEGMENT PROCEDURE OPTIONS; (* P070301 *) Code from: WRITE( ' VERSION 3.0 OF 08-FEB-2024 SER:'); Code to: WRITE( ' VERSION 3.1 OF 24-MAR-2024 SER:'); Final compiled file names: SYSTEM.STARTUP Destination disk: Any Wizardry Proving Grounds boot disks. Enhancement #: WC048 - Quickplot To Stop Update Hit Points of Poisoned Characters ================================================================================== Status: Fixed. Recompiled. Verified. Date of change: 27-Jan-2026. Contributors: Eric Labelle. Enhancements: WC045 added code to automatically update the remaining hit points of poisoned characters in the status window while walking in the maze. This WC048 now checks if the game option Q)UICK PLOT is ON, if ON then the game engine stops updating the characters statistics and the screen draws much faster. Press Q)UICK PLOT again to turn it back OFF. Following are the programming code details ========================================== Source disk: Wiz1C.dsk File: RUNNER2.TEXT Procedure: PROCEDURE UPDATEHP; (* P010E1C *) Code from: . . . IF SHOWPOIS = 1 THEN PRSTATS Code to: . . . IF SHOWPOIS = 1 THEN IF NOT QUICKPLT THEN (* WC048 STOP REFRESH STATS IF QUICKPLOT ON *) PRSTATS Final compiled file names: WIZARDRY.CODE Destination disk: All Wizardry Proving Grounds boot and scenario disks. Enhancement #: WC049 - New Fonts ================================= Status: Fixed. Recompiled. Verified. Date of change: 27-Jan-2026. Creator/Contributors: 4am. Insertion in this project: Eric Labelle. Enhancements: 4am provided new fonts that are easier to read and easier on the eyes. Following are the programming code details ========================================== Source disk: Wizardry scenario disk. File: SCENARIO.DATA Tool: Use Copy II Plus 5.5 - Sector Editor Method: The normal hi-res character set are located at block offset 1. That is Hex 200 to Hex 3ff. Copy those from 4am's release in Wizardry Replay 2.0 that includes his fonts to the destination scenario disk. Note: This is track 12 hex, sectors 3 hex and 2 hex. Destination disk: Any Wizardry scenario disks. Enhancement #: WC050 - Chute Pause =================================== Status: Fixed. Recompiled. Verified. Date of change: 11-Feb-2026. Contributors: Eric Labelle. Enhancements: Added a pause with extra text after stepping on a CHUTE square in the maze. When playing with an emulator, and especially at faster game speeds, the "A CHUTE!" message was dissapearing too fast to see what happened. Following are the programming code details ========================================== Source disk: Wiz1C.dsk File: RUNNER2.TEXT Procedure: PROCEDURE ACHUTE; (* P010E13 *) Code from: BEGIN PRINTSTR( 'A CHUTE!'); QUIETXFR END; Code to: BEGIN PRINTSTR( 'A CHUTE!'); MVCURSOR( 1, 13); (* WC050 INSERT PAUSE *) PRINTSTR( 'PRESS A KEY TO SCRAMBLE'); MVCURSOR( 1, 14); PRINTSTR( 'BACK TO YOUR FEET!'); GETKEY; QUIETXFR END; Final compiled file names: WIZARDRY.CODE Destination disk: All Wizardry Proving Grounds boot and scenario disks. Bug/Issue #: WC051 - Fizzle Fix ================================== Status: Fixed. Recompiled. Verified. Date of change: 12-Feb-2026. Contributors: Eric Labelle. Fix: Game breaker fix. When stepping on a square which has the FIZZLES attribute, all spells for monsters and your party fail, even if in camp. The problem was that if you stepped on any normal square thereafter the FIZZLES effect did not stop. This meant for example if you got in a tough fight and needed to heal (or MALOR/Teleport out, he, he, he) you couldn't do it, and furthermore you could not cast spells in the next fight either, which often unfairly got your entire party slaughtered. With this fix, now stepping out of a warded FIZZLES square gives you party a chance to cast spells again and survive. Following are the programming code details ========================================== Source disk: Wiz1C.dsk File: RUNNER2.TEXT Procedure: PROCEDURE RUNMAIN; (* P010E0E *) Code from: BEGIN (* RUNMAIN *) . . . IF MAZE.SQRETYPE[ MAZE.SQREXTRA[ MAZEX][ MAZEY]] <> NORMAL THEN IF XGOTO2 <> XSCNMSG THEN IF INITTURN THEN SPECSQAR; . . . Code to: . . . IF MAZE.SQRETYPE[ MAZE.SQREXTRA[ MAZEX][ MAZEY]] = NORMAL THEN FIZZLES := 0; (* WC051 CANCEL FIZZLE IS NOT ON A FIZZLE SQUARE *) IF MAZE.SQRETYPE[ MAZE.SQREXTRA[ MAZEX][ MAZEY]] <> NORMAL THEN IF XGOTO2 <> XSCNMSG THEN IF INITTURN THEN SPECSQAR; . . . Final compiled file names: WIZARDRY.CODE Destination disk: All Wizardry Proving Grounds boot and scenario disks. Release #: WC052 - Release 14 Feb 2026 v3.1.1 - Last-Before-RNG-Fix ======================================================================== Status: Fixed. Recompiled. Verified. Date of change: 14-Feb-2026. Contributors: Eric Labelle. Enhancements: Fully recompiled release v3.1.1 as of 14 Feb 2026. This is the last release before the random number generator and use of safe memory location fixes by Qkumba. Following are the programming code details ========================================== Source disk: Wiz1E.dsk File: OPTIONS.TEXT Procedure: SEGMENT PROCEDURE OPTIONS; (* P070301 *) Code from: WRITE( ' VERSION 3.1 OF 24-MAR-2024 SER:'); Code to: WRITE( 'VERSION 3.1.1 OF 14-FEB-2026 SER:'); Final compiled file names: SYSTEM.STARTUP Destination disk: Any Wizardry Proving Grounds boot disks. Bug/Issue #: WC053 - Random Number Generator Fix =================================================== Status: Fixed. Recompiled. Verified. Date of change: 17-Mar-2026. Bug reported by: Thomas William Ewers Code by: Peter Ferrie (Qkumba) main code and solution, with adjustments to other affected files by Eric Labelle Recompiled by: Eric Labelle Fix: This fix is to use safe memory locations in Assembly and to fix the Random Number Generator bug. My sincere thanks to Qkumba for performing yet another incredible feat. Following are the programming code details ========================================== Source disk: Wiz1D.dsk Files: CLRPICT.TEXT, DRAWLINE.TEXT, MVCURSOR.TEXT, PRGRCHR.TEXT, RANDOM.TEXT Code from: .PROC CLRPICT,4 ; P01001A,4 ; 4 PARAMETERS ; .REF L5AE4, L5B33 ; REFERENCE HI RES SCREEN MEMORY POINTERS (LEFT EDGE) START WITH LINE 5. ; ; ; CLEAR "PICTURE" AREA OF SCREEN (82 X 79 PIXELS) ; ; -OR- ; ; SET VALID RECTANGLE COORDINATES ; ; PLA ; POP RETURN STA 00 PLA STA 01 ; PLA STA 06 ; 06 := PARAM 4 PLA LDA 06 CMP #064 ; PARAMETER 4 = 100? BEQ L5BF5 ; YES, L5BF5 (CLEAR PICTURE AREA) CMP #065 ; PARAMETER 4 = 101? BEQ L5BC3 ; YES, L5BC3 (FOR WIZARDRY I IT IS NEVER 101) ; ; $7F9, $779, $6F9, $679 ARE SLOT #1 RAM SCRATCHPAD!? ; ; ; SET UP VALID RECTANGLE DRAWING REGION (BOUNDARIES) ; ; STA 007F9 ; $7F9 = PARAM 4 Y UPPER BOUNDARY (ALWAYS 79) PLA STA 00779 ; $779 = PARAM 3 X UPPER BOUNDARY PLA PLA STA 006F9 ; $6F9 = PARAM 2 Y LOWER BOUNDARY (ALWAYS 0) PLA PLA STA 00679 ; $679 = PARAM 1 X LOWER BOUNDARY PLA ; LDA 01 ; PUSH RETURN PHA LDA 00 PHA RTS ; ; ; L5BC3 ; PARAM 4 SET TO 101 (NEVER EXECUTED) PLA STA 06 PLA STA 07 PLA PLA PLA PLA LDA 01 PHA LDA 00 PHA CLC CLD LDA #04E STA 04 L5BD9 JSR L5C0E DEC 04 CMP #040 BNE L5BD9 L5BE2 JSR L5C34 DEC 04 CMP #0D BNE L5BE2 L5BEB JSR L5C0E DEC 04 BNE L5BEB JMP L5C0E ; ; ; CLEAR PICTURE DISPLAY AREA ; ; 79 LINES X 82 COLUMNS OF PIXELS ON THE HI RES SCREEN. ; ; START WITH LINE 5 (ZERO BASED) AND END WITH LINE 83 (ZERO BASED). ; START WITH COLUMN 4 (ZERO BASED) AND END WITH COLUMN 85 (ZERO BASED). ; L5BF5 ; PARAM 4 = 100. PLA ; THROW AWAY ALL PARAMETERS. PLA PLA PLA PLA PLA LDA 01 ; PUSH RETURN ADDRESS PHA LDA 00 PHA ; CLC CLD LDA #04E ; EXECUTE L5C0E (CLEAR LINE) 79 TIMES STA 04 L5C07 JSR L5C0E DEC 04 BNE L5C07 ; ; CLEAR 82 HORIZONTAL PIXELS (MAINTAIN FIRST 4 PIXELS ON LINE) ; L5C0E LDX 04 ; INDEX INTO HI-RES LINE PTRS. LINES 5 TO 83. (DECIMAL, BASE 0) LDA L5AE4,X ; START AT BOTTOM OF SCREEN AND WORK UPWARDS STA 02 LDA L5B33,X STA 03 ; $02.03 HAVE ADDRESS OF LEFT EDGE OF HI-RES SCREEN ; LDX #0B ; CLEAR 11 FULL BYTES (7 X 11 = 77 SCREEN PIXELS) LDY #00 LDA #0F ; MAINTAIN FIRST 4 LEFTMOST PIXELS ON THIS LINE, AND @2,Y ; BUT CLEAR THE OTHER 3 PIXELS IN THIS BYTE STA @2,Y INY LDA #00 ; CLEAR 7 DISPLAYABLE PIXELS FOR EACH BYTE OF HI RES MEMORY ; L5C27 STA @2,Y INY DEX BNE L5C27 ; CLEAR 11 FULL BYTES (7 X 11 = 77 SCREEN PIXELS) ; LDA #0FC ; IN NEXT BYTE, CLEAR FIRST 2 LEFTMOST PIXELS BUT MAINTAIN AND @2,Y ; OTHER 5 DISPLAYABLE PIXELS. STA @2,Y ; 3 + 77 + 2 = 82 PIXELS RTS ; ; ; L5C34 ; PART OF L5BC3 CODE. NEVER EXECUTED. LDX 04 LDA L5AE4,X STA 02 LDA L5B33,X STA 03 LDX #0B LDY #00 LDA #0F AND @2,Y STA @2,Y INY L5C4B LDA @6,Y STA @2,Y INY DEX BNE L5C4B LDA #0FC AND @2,Y STA @2,Y CLC LDA 06 ADC #0A STA 06 LDA 07 ADC #00 STA 07 RTS .END Code to: .PROC CLRPICT,4 ; P01001A,4 ; 4 PARAMETERS ; ; ; FIX WC053 - CODE BY QKUMBA TO USE SAFE MEMORY LOCATIONS ; ; AND FIX THE RANDOM NUMBER GENERATOR BUG BY REPLACING ; ; $047A,$04FA,$057A,$05FB,$04F9,$0579,$0679,$06F9,$0779,$07F9 BY ; ; $BFF0,$BFF1,$BFF2,$BFF3,$BFF4,$BFF5,$BFF9,$BFFA,$BFFB,$BFFC ; .REF L5AE4, L5B33 ; REFERENCE HI RES SCREEN MEMORY POINTERS (LEFT EDGE) START WITH LINE 5. ; ; ; CLEAR "PICTURE" AREA OF SCREEN (82 X 79 PIXELS) ; ; -OR- ; ; SET VALID RECTANGLE COORDINATES ; ; PLA ; POP RETURN STA 00 PLA STA 01 ; PLA STA 06 ; 06 := PARAM 4 PLA LDA 06 CMP #064 ; PARAMETER 4 = 100? BEQ L5BF5 ; YES, L5BF5 (CLEAR PICTURE AREA) CMP #065 ; PARAMETER 4 = 101? BEQ L5BC3 ; YES, L5BC3 (FOR WIZARDRY I IT IS NEVER 101) ; ; $BFF9, $BFFA, $BFFB, $BFFC RAM SCRATCHPAD!? ; ; ; SET UP VALID RECTANGLE DRAWING REGION (BOUNDARIES) ; ; STA 0BFFC ; $BFFC = PARAM 4 Y UPPER BOUNDARY (ALWAYS 79) PLA STA 0BFFB ; $BFFB = PARAM 3 X UPPER BOUNDARY PLA PLA STA 0BFFA ; $BFFA = PARAM 2 Y LOWER BOUNDARY (ALWAYS 0) PLA PLA STA 0BFF9 ; $BFF9 = PARAM 1 X LOWER BOUNDARY PLA ; LDA 01 ; PUSH RETURN PHA LDA 00 PHA RTS ; ; ; L5BC3 ; PARAM 4 SET TO 101 (NEVER EXECUTED) PLA STA 06 PLA STA 07 PLA PLA PLA PLA LDA 01 PHA LDA 00 PHA CLC CLD LDA #04E STA 04 L5BD9 JSR L5C0E DEC 04 CMP #040 BNE L5BD9 L5BE2 JSR L5C34 DEC 04 CMP #0D BNE L5BE2 L5BEB JSR L5C0E DEC 04 BNE L5BEB JMP L5C0E ; ; ; CLEAR PICTURE DISPLAY AREA ; ; 79 LINES X 82 COLUMNS OF PIXELS ON THE HI RES SCREEN. ; ; START WITH LINE 5 (ZERO BASED) AND END WITH LINE 83 (ZERO BASED). ; START WITH COLUMN 4 (ZERO BASED) AND END WITH COLUMN 85 (ZERO BASED). ; L5BF5 ; PARAM 4 = 100. PLA ; THROW AWAY ALL PARAMETERS. PLA PLA PLA PLA PLA LDA 01 ; PUSH RETURN ADDRESS PHA LDA 00 PHA ; CLC CLD LDA #04E ; EXECUTE L5C0E (CLEAR LINE) 79 TIMES STA 04 L5C07 JSR L5C0E DEC 04 BNE L5C07 ; ; CLEAR 82 HORIZONTAL PIXELS (MAINTAIN FIRST 4 PIXELS ON LINE) ; L5C0E LDX 04 ; INDEX INTO HI-RES LINE PTRS. LINES 5 TO 83. (DECIMAL, BASE 0) LDA L5AE4,X ; START AT BOTTOM OF SCREEN AND WORK UPWARDS STA 02 LDA L5B33,X STA 03 ; $02.03 HAVE ADDRESS OF LEFT EDGE OF HI-RES SCREEN ; LDX #0B ; CLEAR 11 FULL BYTES (7 X 11 = 77 SCREEN PIXELS) LDY #00 LDA #0F ; MAINTAIN FIRST 4 LEFTMOST PIXELS ON THIS LINE, AND @2,Y ; BUT CLEAR THE OTHER 3 PIXELS IN THIS BYTE STA @2,Y INY LDA #00 ; CLEAR 7 DISPLAYABLE PIXELS FOR EACH BYTE OF HI RES MEMORY ; L5C27 STA @2,Y INY DEX BNE L5C27 ; CLEAR 11 FULL BYTES (7 X 11 = 77 SCREEN PIXELS) ; LDA #0FC ; IN NEXT BYTE, CLEAR FIRST 2 LEFTMOST PIXELS BUT MAINTAIN AND @2,Y ; OTHER 5 DISPLAYABLE PIXELS. STA @2,Y ; 3 + 77 + 2 = 82 PIXELS RTS ; ; ; L5C34 ; PART OF L5BC3 CODE. NEVER EXECUTED. LDX 04 LDA L5AE4,X STA 02 LDA L5B33,X STA 03 LDX #0B LDY #00 LDA #0F AND @2,Y STA @2,Y INY L5C4B LDA @6,Y STA @2,Y INY DEX BNE L5C4B LDA #0FC AND @2,Y STA @2,Y CLC LDA 06 ADC #0A STA 06 LDA 07 ADC #00 STA 07 RTS .END Code from: .PROC DRAWLINE,5 ; P01001B,5 ; 5 PARAMETERS ; .DEF L5AE4, L5B33 ; DEFINE POINTERS TO HI RES SCREEN LEFT EDGE STARTING WITH LINE 5. ; ; THIS ROUTINE USES $679, $6F9, $779, $07F9 SET PREVIOUSLY BY ; CLRPICT PROCEDURE (WITH THE LAST PARAMETER NOT SET TO 100 OR 101). ; ; THOSE VALUES DETERMINE THE VALID RECTANGLE DRAWING REGION. ; CLC CLD PLA ; POP RETURN STA 00 PLA STA 01 PLA STA 0C ; 0C := PARM 5 LINE LENGTH (MAX NUMBER OF PIXELS TO DRAW) PLA PLA STA 0A ; 0A := PARM 4 DELTA VERTICAL ( -1, 0, +1) PLA PLA STA 08 ; 08 := PARM 3 DELTA HORIZONTAL ( -1, 0, +1) PLA PLA STA 06 ; 06 := PARM 2 Y COORDINATE PLA PLA STA 04 ; 04 := PARM 1 X COORDINATE (0,0) IS UPPER LEFT IN "PICTURE" PLA ; LDA 01 ; PUSH RETURN PHA LDA 00 PHA ; L59FA LDA 04 ; SEE IF X COORDINATE IS OUTSIDE DRAWING BOUNDARY CMP 00679 BMI L5A2C ; YES, L5A2C CMP 00779 BEQ L5A08 BPL L5A2C ; YES, L5A2C L5A08 TAX LDA 06 ; SEE IF Y COORDINATE IS OUTSIDE DRAWING BOUNDARY CMP 006F9 BMI L5A2C ; YES, L5A2C CMP 007F9 BEQ L5A17 BPL L5A2C ; YES, L5A2C ; L5A17 ; ; ; PREPARE TO DRAW A PIXEL ; TAY LDA L5AE4,Y ; SET UP POINTER TO HI RES SCREEN LOCATION STA 02 ; L5AE4 TABLE STARTS WITH LINE 5 OF HI RES (ZERO BASED) LDA L5B33,Y STA 03 LDY L5A40,X ; GET BYTE OFFSET FROM LEFT EDGE OF SCREEN MEMORY MAP LDA L5A92,X ; LOAD 1 BIT INTO A (1 MEMORY LOCATION HOLDS 7 SCREEN PIXELS) ORA @2,Y ; SET 1 BIT ON SCREEN STA @2,Y ; SET 1 BIT ON SCREEN L5A2C CLC ; ADVANCE TO NEXT HORIZONTAL POSITION (-1, 0, +1) LDA 04 ADC 08 STA 04 CLC ; ADVANCE TO NEXT VERTICAL POSITION (-1, 0, +1) LDA 06 ADC 0A STA 06 CLC ; DEC LINE LENGTH COUNTER DEC 0C BNE L59FA ; DO ANOTHER PIXEL ALONG THE LINE. RTS ; L5A40 ; ; HORIZONTAL OFFSET TO DETERMINE HI RES MEMORY MAPPED SCREEN LOCATION. ; THE FIRST 4 COLUMNS OF HI RES ARE NOT PART OF THE "PICTURE" AREA. ; ; THIS TABLE IS INDEXED BY THE HORIZONTAL PIXEL POSTION. ; .BYTE 000, 000, 000 .BYTE 001, 001, 001, 001, 001, 001, 001 .BYTE 002, 002, 002, 002, 002, 002, 002 .BYTE 003, 003, 003, 003, 003, 003, 003 .BYTE 004, 004, 004, 004, 004, 004, 004 .BYTE 005, 005, 005, 005, 005, 005, 005 .BYTE 006, 006, 006, 006, 006, 006, 006 .BYTE 007, 007, 007, 007, 007, 007, 007 .BYTE 008, 008, 008, 008, 008, 008, 008 .BYTE 009, 009, 009, 009, 009, 009, 009 .BYTE 00A, 00A, 00A, 00A, 00A, 00A, 00A .BYTE 00B, 00B, 00B, 00B, 00B, 00B, 00B .BYTE 00C, 00C ; L5A92 ; ; PIXEL POSITION IN MEMORY MAPPED SCREEN LOCATION ; THERE ARE 7 PIXELS PER BYTE (HI BIT NOT USED AS PIXEL BIT). ; LOW ORDER BIT IS LEFTMOST ONE DISPLAYED ON SCREEN FOR THAT BYTE. ; ; THE FIRST 4 COLUMNS ON HI RES ARE NOT PART OF THE "PICTURE" AREA. ; .BYTE 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002 ; L5AE4 ; ; HI RES PAGE 1 LEFT EDGE SCREEN MEMORY PTR (LOW PART). ; THE TABLE STARTS WITH LINE 5 OF HI RES SCREEN. ; THIS IS THE "PICTURE" PART OF WIZARDRY DISPLAY WHERE THE MAZE ; IS DRAWN. THE AREA IS 82 PIXELS WIDE BY 79 PIXELS HIGH. ; .BYTE 000, 000, 000 .BYTE 080, 080, 080, 080, 080, 080, 080, 080 .BYTE 000, 000, 000, 000, 000, 000, 000, 000 .BYTE 080, 080, 080, 080, 080, 080, 080, 080 .BYTE 000, 000, 000, 000, 000, 000, 000, 000 .BYTE 080, 080, 080, 080, 080, 080, 080, 080 .BYTE 000, 000, 000, 000, 000, 000, 000, 000 .BYTE 080, 080, 080, 080, 080, 080, 080, 080 .BYTE 028, 028, 028, 028, 028, 028, 028, 028 .BYTE 0A8, 0A8, 0A8, 0A8, 0A8, 0A8, 0A8, 0A8 .BYTE 028, 028, 028, 028 ; L5B33 ; ; HI RES PAGE 1 LEFT EDGE SCREEN MEMORY PTR (HIGH PART) ; .BYTE 034, 038, 03C .BYTE 020, 024, 028, 02C, 030, 034, 038, 03C .BYTE 021, 025, 029, 02D, 031, 035, 039, 03D .BYTE 021, 025, 029, 02D, 031, 035, 039, 03D .BYTE 022, 026, 02A, 02E, 032, 036, 03A, 03E .BYTE 022, 026, 02A, 02E, 032, 036, 03A, 03E .BYTE 023, 027, 02B, 02F, 033, 037, 03B, 03F .BYTE 023, 027, 02B, 02F, 033, 037, 03B, 03F .BYTE 020, 024, 028, 02C, 030, 034, 038, 03C .BYTE 020, 024, 028, 02C, 030, 034, 038, 03C .BYTE 021, 025, 029, 02D .END Code to: .PROC DRAWLINE,5 ; P01001B,5 ; 5 PARAMETERS ; ; ; FIX WC053 - CODE BY QKUMBA TO USE SAFE MEMORY LOCATIONS ; ; AND FIX THE RANDOM NUMBER GENERATOR BUG BY REPLACING ; ; $047A,$04FA,$057A,$05FB,$04F9,$0579,$0679,$06F9,$0779,$07F9 BY ; ; $BFF0,$BFF1,$BFF2,$BFF3,$BFF4,$BFF5,$BFF9,$BFFA,$BFFB,$BFFC ; .DEF L5AE4, L5B33 ; DEFINE POINTERS TO HI RES SCREEN LEFT EDGE STARTING WITH LINE 5. ; ; THIS ROUTINE USES $BFF9, $BFFA, $BFFB, $BFFC SET PREVIOUSLY BY ; CLRPICT PROCEDURE (WITH THE LAST PARAMETER NOT SET TO 100 OR 101). ; ; THOSE VALUES DETERMINE THE VALID RECTANGLE DRAWING REGION. ; CLC CLD PLA ; POP RETURN STA 00 PLA STA 01 PLA STA 0C ; 0C := PARM 5 LINE LENGTH (MAX NUMBER OF PIXELS TO DRAW) PLA PLA STA 0A ; 0A := PARM 4 DELTA VERTICAL ( -1, 0, +1) PLA PLA STA 08 ; 08 := PARM 3 DELTA HORIZONTAL ( -1, 0, +1) PLA PLA STA 06 ; 06 := PARM 2 Y COORDINATE PLA PLA STA 04 ; 04 := PARM 1 X COORDINATE (0,0) IS UPPER LEFT IN "PICTURE" PLA ; LDA 01 ; PUSH RETURN PHA LDA 00 PHA ; L59FA LDA 04 ; SEE IF X COORDINATE IS OUTSIDE DRAWING BOUNDARY CMP 0BFF9 BMI L5A2C ; YES, L5A2C CMP 0BFFB BEQ L5A08 BPL L5A2C ; YES, L5A2C L5A08 TAX LDA 06 ; SEE IF Y COORDINATE IS OUTSIDE DRAWING BOUNDARY CMP 0BFFA BMI L5A2C ; YES, L5A2C CMP 0BFFC BEQ L5A17 BPL L5A2C ; YES, L5A2C ; L5A17 ; ; ; PREPARE TO DRAW A PIXEL ; TAY LDA L5AE4,Y ; SET UP POINTER TO HI RES SCREEN LOCATION STA 02 ; L5AE4 TABLE STARTS WITH LINE 5 OF HI RES (ZERO BASED) LDA L5B33,Y STA 03 LDY L5A40,X ; GET BYTE OFFSET FROM LEFT EDGE OF SCREEN MEMORY MAP LDA L5A92,X ; LOAD 1 BIT INTO A (1 MEMORY LOCATION HOLDS 7 SCREEN PIXELS) ORA @2,Y ; SET 1 BIT ON SCREEN STA @2,Y ; SET 1 BIT ON SCREEN L5A2C CLC ; ADVANCE TO NEXT HORIZONTAL POSITION (-1, 0, +1) LDA 04 ADC 08 STA 04 CLC ; ADVANCE TO NEXT VERTICAL POSITION (-1, 0, +1) LDA 06 ADC 0A STA 06 CLC ; DEC LINE LENGTH COUNTER DEC 0C BNE L59FA ; DO ANOTHER PIXEL ALONG THE LINE. RTS ; L5A40 ; ; HORIZONTAL OFFSET TO DETERMINE HI RES MEMORY MAPPED SCREEN LOCATION. ; THE FIRST 4 COLUMNS OF HI RES ARE NOT PART OF THE "PICTURE" AREA. ; ; THIS TABLE IS INDEXED BY THE HORIZONTAL PIXEL POSTION. ; .BYTE 000, 000, 000 .BYTE 001, 001, 001, 001, 001, 001, 001 .BYTE 002, 002, 002, 002, 002, 002, 002 .BYTE 003, 003, 003, 003, 003, 003, 003 .BYTE 004, 004, 004, 004, 004, 004, 004 .BYTE 005, 005, 005, 005, 005, 005, 005 .BYTE 006, 006, 006, 006, 006, 006, 006 .BYTE 007, 007, 007, 007, 007, 007, 007 .BYTE 008, 008, 008, 008, 008, 008, 008 .BYTE 009, 009, 009, 009, 009, 009, 009 .BYTE 00A, 00A, 00A, 00A, 00A, 00A, 00A .BYTE 00B, 00B, 00B, 00B, 00B, 00B, 00B .BYTE 00C, 00C ; L5A92 ; ; PIXEL POSITION IN MEMORY MAPPED SCREEN LOCATION ; THERE ARE 7 PIXELS PER BYTE (HI BIT NOT USED AS PIXEL BIT). ; LOW ORDER BIT IS LEFTMOST ONE DISPLAYED ON SCREEN FOR THAT BYTE. ; ; THE FIRST 4 COLUMNS ON HI RES ARE NOT PART OF THE "PICTURE" AREA. ; .BYTE 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002, 004, 008, 010, 020, 040 .BYTE 001, 002 ; L5AE4 ; ; HI RES PAGE 1 LEFT EDGE SCREEN MEMORY PTR (LOW PART). ; THE TABLE STARTS WITH LINE 5 OF HI RES SCREEN. ; THIS IS THE "PICTURE" PART OF WIZARDRY DISPLAY WHERE THE MAZE ; IS DRAWN. THE AREA IS 82 PIXELS WIDE BY 79 PIXELS HIGH. ; .BYTE 000, 000, 000 .BYTE 080, 080, 080, 080, 080, 080, 080, 080 .BYTE 000, 000, 000, 000, 000, 000, 000, 000 .BYTE 080, 080, 080, 080, 080, 080, 080, 080 .BYTE 000, 000, 000, 000, 000, 000, 000, 000 .BYTE 080, 080, 080, 080, 080, 080, 080, 080 .BYTE 000, 000, 000, 000, 000, 000, 000, 000 .BYTE 080, 080, 080, 080, 080, 080, 080, 080 .BYTE 028, 028, 028, 028, 028, 028, 028, 028 .BYTE 0A8, 0A8, 0A8, 0A8, 0A8, 0A8, 0A8, 0A8 .BYTE 028, 028, 028, 028 ; L5B33 ; ; HI RES PAGE 1 LEFT EDGE SCREEN MEMORY PTR (HIGH PART) ; .BYTE 034, 038, 03C .BYTE 020, 024, 028, 02C, 030, 034, 038, 03C .BYTE 021, 025, 029, 02D, 031, 035, 039, 03D .BYTE 021, 025, 029, 02D, 031, 035, 039, 03D .BYTE 022, 026, 02A, 02E, 032, 036, 03A, 03E .BYTE 022, 026, 02A, 02E, 032, 036, 03A, 03E .BYTE 023, 027, 02B, 02F, 033, 037, 03B, 03F .BYTE 023, 027, 02B, 02F, 033, 037, 03B, 03F .BYTE 020, 024, 028, 02C, 030, 034, 038, 03C .BYTE 020, 024, 028, 02C, 030, 034, 038, 03C .BYTE 021, 025, 029, 02D .END Code from: .PROC MVCURSOR,2 ; 2 PARAMETERS ; P01001F,2 ; ; ; CALL: MVCURSOR (X, Y); ; ; ; ; IN THIS ROUTINE: ; ; ; ; X STORED AT $4F9 (SLOT #1 RAM SPACE) ; ; Y STORED AT $579 (SLOT #1 RAM SPACE) ; ; ; ; PRGRCHR USES $4F9 AND $579 ; ; ; ; MVCURSOR( 40, Y) TURN ON GRAPHICS MODE ; ; MVCUROSR( 50, Y) TURN ON TEXT MODE ; ; MVCURSOR( 60, Y) JUMP TO $2002 (COPY PROTECTION) ; ; MVCURSOR( 70, Y) CRASH AND BURN (COPY PROTECTION) ; ; MVCURSOR( 80, Y) ADJUST RANDOM # (UNTIL KEY IS AVAILABLE) ; ; $47A, $47B, $47C, $47D (???) ; ; RNG USES: $47A, $4FA, $57A, $5FB (!!!) ; PLA ; PULL RETURN STA 00 PLA STA 01 ; PLA ; PARAM 2 08 := Y COORDINATE STA 08 PLA PLA ; PARAM 1 06 := X COORDINATE STA 06 PLA ; LDA 01 ; PUSH RETURN PHA LDA 00 PHA ; LDA 06 CMP #028 ; X = 40? BEQ L58EF ; YES, L58EF ; CMP #032 ; X = 50? BEQ L58FC ; YES, L58FC ; CMP #03C ; X = 60? BEQ L5909 ; YES, L5909 ; CMP #046 ; X = 70? BEQ L590C ; YES, L590C ; CMP #050 ; X = 80? BEQ L5920 ; YES, L5920 ; ; ; X NOT A "SPECIAL" VALUE ; STA 004F9 ; SAVE "X" COORDINATE (AT SLOT #1 RAM SPACE) LDA 08 STA 00579 ; SAVE "Y" COORDINATE (AT SLOT #1 RAM SPACE) RTS ; L58EF ; ; ; TURN ON GRAPHICS MODE ; STA 0C050 ; GRAPHICS STA 0C054 ; PRIMARY PAGE STA 0C057 ; HI RES STA 0C052 ; ALL GRAPHICS RTS ; L58FC ; ; ; TURN ON TEXT MODE ; STA 0C051 ; TEXT STA 0C054 ; PRIMARY PAGE STA 0C056 ; LO RES STA 0C052 ; ALL TEXT RTS ; L5909 ; ; ; EXECUTE COPY PROTECTION CODE ; ; CODE AT $2002 WAS LOADED FROM SCENARIO.DATA ON SIDE 2 OF DISK ; ; JMP 02002 ; ; L590C ; ; ; CRASH AND BURN (PART OF COPY PROTECTION CODE) ; LDA #0BF ; START AT $BF00..$BFFF STA 03 LDA #00 STA 02 ; L5914 LDY #00 L5916 STA @2,Y ; STORE 0 DEY BNE L5916 ; DO 256 BYTES ; DEC 03 ; CONTINUE DOWNWARD THROUGH MEMORY JMP L5914 ; EVENTUALLY THE SYSTEM WILL EXECUTE A 0 INSTRUCTION ; WHICH IS A BRK INSTRUCTION. SINCE THE BRK VECTORS ; HAVE ALREADY BEEN CHANGED, THE MONITOR WILL REBOOT. ; L5920 ; ; ; ADJUST RANDOM # UNTIL KEY IS AVAILABLE FROM INPUT BUFFER ; ; OR A KEY IS PRESSED. ; LDA 0C083 ; SELECT RAM CARD RAM READ, BANK 2 JSR 0BF0A ; $BF0A IS CONCK IN SYSCOM (PASCAL OS) LDA 0C083 LDA 0BF18 ; $BF18 IS RPTR IN SYSCOM (PASCAL OS) CMP 0BF19 ; $BF19 IS WPTR IN SYSCOM (PASCAL OS) BNE L5942 ; CIRCULAR INPUT BUFFER. WHEN EQUAL, THEN NO CHARACTERS AVAILABLE. ; ; ; NO CHARACTER WAS IN THE INPUT BUFFER L5931 LDX #00 L5933 INC 0047A,X ; INCREMENT RANDOM # (BUG !!!!!!) BNE L593D ; $47A, $47B, $47C, $47D (??????????) INX ; RAM FOR SLOTS #2, #3, #4, #5 CPX #04 ; BNE L5933 ; RNG CODE USES $47A, $4FA, $57A, $5FB (ALL SLOT #2) L593D LDA 0C000 ; KEYBOARD DATA BPL L5931 ; KEY PRESSED? NO, L5931 (CONTINUE INCREMENTING RANDOM #) ; L5942 ; ; YES, A KEY WAS PRESSED (OR IS AVAILABLE FROM INPUT BUFFER) LDA 0C08B ; RAM CARD RAM READ, BANK 1 RTS .END Code to: .PROC MVCURSOR,2 ; 2 PARAMETERS ; P01001F,2 ; ; ; FIX WC053 - CODE BY QKUMBA TO USE SAFE MEMORY LOCATIONS ; ; AND FIX THE RANDOM NUMBER GENERATOR BUG BY REPLACING ; ; $047A,$04FA,$057A,$05FB,$04F9,$0579,$0679,$06F9,$0779,$07F9 BY ; ; $BFF0,$BFF1,$BFF2,$BFF3,$BFF4,$BFF5,$BFF9,$BFFA,$BFFB,$BFFC ; ; ; CALL: MVCURSOR (X, Y); ; ; ; ; IN THIS ROUTINE: ; ; ; ; X STORED AT $BFF4 ; ; Y STORED AT $BFF5 ; ; ; ; PRGRCHR USES $BFF4 AND $BFF5 ; ; ; ; MVCURSOR( 40, Y) TURN ON GRAPHICS MODE ; ; MVCUROSR( 50, Y) TURN ON TEXT MODE ; ; MVCURSOR( 60, Y) JUMP TO $2002 (COPY PROTECTION) ; ; MVCURSOR( 70, Y) CRASH AND BURN (COPY PROTECTION) ; ; MVCURSOR( 80, Y) ADJUST RANDOM # (UNTIL KEY IS AVAILABLE) ; ; RNG USES: $BFF0, $BFF1, $BFF2, $BFF3 ; PLA ; PULL RETURN STA 00 PLA STA 01 ; PLA ; PARAM 2 08 := Y COORDINATE STA 08 PLA PLA ; PARAM 1 06 := X COORDINATE STA 06 PLA ; LDA 01 ; PUSH RETURN PHA LDA 00 PHA ; LDA 06 CMP #028 ; X = 40? BEQ L58EF ; YES, L58EF ; CMP #032 ; X = 50? BEQ L58FC ; YES, L58FC ; CMP #03C ; X = 60? BEQ L5909 ; YES, L5909 ; CMP #046 ; X = 70? BEQ L590C ; YES, L590C ; CMP #050 ; X = 80? BEQ L5920 ; YES, L5920 ; ; ; X NOT A "SPECIAL" VALUE ; STA 0BFF4 ; SAVE "X" COORDINATE LDA 08 STA 0BFF5 ; SAVE "Y" COORDINATE RTS ; L58EF ; ; ; TURN ON GRAPHICS MODE ; STA 0C050 ; GRAPHICS STA 0C054 ; PRIMARY PAGE STA 0C057 ; HI RES STA 0C052 ; ALL GRAPHICS RTS ; L58FC ; ; ; TURN ON TEXT MODE ; STA 0C051 ; TEXT STA 0C054 ; PRIMARY PAGE STA 0C056 ; LO RES STA 0C052 ; ALL TEXT RTS ; L5909 ; ; ; EXECUTE COPY PROTECTION CODE ; ; CODE AT $2002 WAS LOADED FROM SCENARIO.DATA ON SIDE 2 OF DISK ; ; JMP 02002 ; ; L590C ; ; ; CRASH AND BURN (PART OF COPY PROTECTION CODE) ; LDA #0BF ; START AT $BF00..$BFFF STA 03 LDA #00 STA 02 ; L5914 LDY #00 L5916 STA @2,Y ; STORE 0 DEY BNE L5916 ; DO 256 BYTES ; DEC 03 ; CONTINUE DOWNWARD THROUGH MEMORY JMP L5914 ; EVENTUALLY THE SYSTEM WILL EXECUTE A 0 INSTRUCTION ; WHICH IS A BRK INSTRUCTION. SINCE THE BRK VECTORS ; HAVE ALREADY BEEN CHANGED, THE MONITOR WILL REBOOT. ; L5920 ; ; ; ADJUST RANDOM # UNTIL KEY IS AVAILABLE FROM INPUT BUFFER ; ; OR A KEY IS PRESSED. ; LDA 0C083 ; SELECT RAM CARD RAM READ, BANK 2 JSR 0BF0A ; $BF0A IS CONCK IN SYSCOM (PASCAL OS) LDA 0C083 LDA 0BF18 ; $BF18 IS RPTR IN SYSCOM (PASCAL OS) CMP 0BF19 ; $BF19 IS WPTR IN SYSCOM (PASCAL OS) BNE L5942 ; CIRCULAR INPUT BUFFER. WHEN EQUAL, THEN NO CHARACTERS AVAILABLE. ; ; ; NO CHARACTER WAS IN THE INPUT BUFFER L5931 LDX #00 L5933 INC 0BFF0,X ; INCREMENT RANDOM # BNE L593D ; $BFF0, $BFF1, $BFF2, $BFF3 INX ; RAM FOR SLOTS #2, #3, #4, #5 CPX #04 ; BNE L5933 ; RNG CODE USES $BFF0, $BFF1, $BFF2, $BFF3 L593D LDA 0C000 ; KEYBOARD DATA BPL L5931 ; KEY PRESSED? NO, L5931 (CONTINUE INCREMENTING RANDOM #) ; L5942 ; ; YES, A KEY WAS PRESSED (OR IS AVAILABLE FROM INPUT BUFFER) LDA 0C08B ; RAM CARD RAM READ, BANK 1 RTS .END Code from: .PROC PRGRCHR,1 ; 1 PARAMETER ; P010020,1 ; ; CALL: PRGRCHR( ACHAR); ; ; ACHAR IS A PACKED ARRAY[ 0..7] OF 0..255; (SEE TCHRIMAG) ; ; PURPOSE: PRINT A CHARACTER TO THE HI RES SCREEN (7 X 8 PIXELS) ; ; USES: $579 IS LINE POSITION ON SCREEN ; $4F9 IS HORIZONTAL POSTION ON SCREEN ; .DEF L0998, L0999 ; PLA ; PULL RETURN STA 00 PLA STA 01 ; PLA ; 02 := CHARACTER TO DISPLAY (PACKED ARRY[ 0..7] OF 0..255) STA 02 PLA STA 03 ; LDA 01 ; PUSH RETURN PHA LDA 00 PHA ; CLD CLC LDA 00579 ; LINE POSITION ASL A ; ADJUST SINCE L5998 AND L5999 HAVE 2 BYTES PER POINTER TAY LDA L5998,Y ; LEFT EDGE OF SCREEN (TOP PIXEL OF CHARACTER) ADC 004F9 ; ADD HORIZONTAL POSITION ON SCREEN STA 04 ; SET 04.05 TO HI RES LOCATION FOR CHARACTER LDA L5999,Y STA 05 LDX #08 ; EACH CHARACTER IS 8 PIXELS HIGH LDY #00 ; L597E ; ; ; PLACE A ROW OF PIXELS ON THE SCREEN FOR THE CHARACTER ; LDA @2,Y ; GET 7 PIXELS OF THE CHARACTER STA @4,Y ; PUT 7 PIXELS ON THE SCREEN INC 05 ; ADVANCE 1 ROW OF PIXELS ON THE SCREEN INC 05 INC 05 INC 05 CLC INC 02 ; INCREMENT TO NEXT ROW OF CHARACTER PIXELS BNE L5991 INC 03 L5991 DEX BNE L597E ; DO ANOTHER ROW UNTIL 8 ARE PLACED ON SCREEN. ; 8 ROWS FOR 1 CHARACTER HAVE BEEN PLACED ON THE SCREEN. INC 004F9 ; ADVANCE HORIZONTAL POSITION RTS ; ; ; ; TABLE OF 24 POINTERS TO LEFT EDGE OF HI RES SCREEN ; ; EACH PTR REPRESENTS ONE "CHARACTER" ROW OF 8 PIXELS. ; L0998 L5998 .BYTE 0 L0999 L5999 .BYTE 020, 080, 020, 000, 021, 080, 021, 000, 022, 080, 022, 000, 023, 080 .BYTE 023, 028, 020, 0A8, 020, 028, 021, 0A8, 021, 028, 022, 0A8, 022, 028 .BYTE 023, 0A8, 023, 050, 020, 0D0, 020, 050, 021, 0D0, 021, 050, 022, 0D0 .BYTE 022, 050, 023, 0D0, 023 .END Code to: .PROC PRGRCHR,1 ; 1 PARAMETER ; P010020,1 ; ; ; FIX WC053 - CODE BY QKUMBA TO USE SAFE MEMORY LOCATIONS ; ; AND FIX THE RANDOM NUMBER GENERATOR BUG BY REPLACING ; ; $047A,$04FA,$057A,$05FB,$04F9,$0579,$0679,$06F9,$0779,$07F9 BY ; ; $BFF0,$BFF1,$BFF2,$BFF3,$BFF4,$BFF5,$BFF9,$BFFA,$BFFB,$BFFC ; ; CALL: PRGRCHR( ACHAR); ; ; ACHAR IS A PACKED ARRAY[ 0..7] OF 0..255; (SEE TCHRIMAG) ; ; PURPOSE: PRINT A CHARACTER TO THE HI RES SCREEN (7 X 8 PIXELS) ; ; USES: $BFF5 IS LINE POSITION ON SCREEN ; $BFF4 IS HORIZONTAL POSTION ON SCREEN ; .DEF L0998, L0999 ; PLA ; PULL RETURN STA 00 PLA STA 01 ; PLA ; 02 := CHARACTER TO DISPLAY (PACKED ARRY[ 0..7] OF 0..255) STA 02 PLA STA 03 ; LDA 01 ; PUSH RETURN PHA LDA 00 PHA ; CLD CLC LDA 0BFF5 ; LINE POSITION ASL A ; ADJUST SINCE L5998 AND L5999 HAVE 2 BYTES PER POINTER TAY LDA L5998,Y ; LEFT EDGE OF SCREEN (TOP PIXEL OF CHARACTER) ADC 0BFF4 ; ADD HORIZONTAL POSITION ON SCREEN STA 04 ; SET 04.05 TO HI RES LOCATION FOR CHARACTER LDA L5999,Y STA 05 LDX #08 ; EACH CHARACTER IS 8 PIXELS HIGH LDY #00 ; L597E ; ; ; PLACE A ROW OF PIXELS ON THE SCREEN FOR THE CHARACTER ; LDA @2,Y ; GET 7 PIXELS OF THE CHARACTER STA @4,Y ; PUT 7 PIXELS ON THE SCREEN INC 05 ; ADVANCE 1 ROW OF PIXELS ON THE SCREEN INC 05 INC 05 INC 05 CLC INC 02 ; INCREMENT TO NEXT ROW OF CHARACTER PIXELS BNE L5991 INC 03 L5991 DEX BNE L597E ; DO ANOTHER ROW UNTIL 8 ARE PLACED ON SCREEN. ; 8 ROWS FOR 1 CHARACTER HAVE BEEN PLACED ON THE SCREEN. INC 0BFF4 ; ADVANCE HORIZONTAL POSITION RTS ; ; ; ; TABLE OF 24 POINTERS TO LEFT EDGE OF HI RES SCREEN ; ; EACH PTR REPRESENTS ONE "CHARACTER" ROW OF 8 PIXELS. ; L0998 L5998 .BYTE 0 L0999 L5999 .BYTE 020, 080, 020, 000, 021, 080, 021, 000, 022, 080, 022, 000, 023, 080 .BYTE 023, 028, 020, 0A8, 020, 028, 021, 0A8, 021, 028, 022, 0A8, 022, 028 .BYTE 023, 0A8, 023, 050, 020, 0D0, 020, 050, 021, 0D0, 021, 050, 022, 0D0 .BYTE 022, 050, 023, 0D0, 023 .END Code from: .FUNC RANDOM,0 ; P01001C,0 ; NO PARAMETERS ; ; ; CALL: RANDOM; ; ; PURPOSE: RETURN A RANDOM NUMBER FROM 0 TO 32,767. ; ; NOTE: USES $47A, $4FA, $57A, $5FB. (SLOT #2 RAM) ; NOTE2: MVCURSOR( 80, X), USED BY GETKEY(), CHANGES ; VALUES OF $47A, AND ; $47B, $47C, $47D (BUG?) ; PLA ; PULL RETURN STA 00 PLA STA 01 ; PLA ; PULL DUMMY SINCE THIS IS A FUNCTION PLA PLA PLA ; LDY #07 ; SHIFT SOME BITS 7 TIMES L5CCC ASL 0047A PHP ROL 004FA ROL 0057A ROL 005FB BMI L5CE0 PLP BPL L5CE6 BMI L5CE3 L5CE0 PLP BMI L5CE6 L5CE3 INC 0047A L5CE6 DEY BNE L5CCC ; PERFORMED 7 SHIFTS YET? NO, L5CCC. ; ; YES LDA 0047A ; HIGH 16 BITS LSR A ; CLEAR HIGH BIT (ENSURES ONLY POSITIVE NUMBER RETURNED) PHA ; LDA 0057A ; USE $57A AS PART OF RANDOM NUMBER LOW 16 BITS PHA ; LDA 01 ; PUSH RETURN PHA LDA 00 PHA RTS .END Code to: .FUNC RANDOM,0 ; P01001C,0 ; NO PARAMETERS ; ; ; FIX WC053 - CODE BY QKUMBA TO USE SAFE MEMORY LOCATIONS ; ; AND FIX THE RANDOM NUMBER GENERATOR BUG BY REPLACING ; ; $047A,$04FA,$057A,$05FB,$04F9,$0579,$0679,$06F9,$0779,$07F9 BY ; ; $BFF0,$BFF1,$BFF2,$BFF3,$BFF4,$BFF5,$BFF9,$BFFA,$BFFB,$BFFC ; ; CALL: RANDOM; ; ; PURPOSE: RETURN A RANDOM NUMBER FROM 0 TO 32,767. ; ; NOTE: USES $BFF0, $BFF1, $BFF2, $BFF3. ; NOTE2: MVCURSOR( 80, X), USED BY GETKEY(), CHANGES ; VALUES OF $BFF0, AND ; $BFF1, $BFF2, $BFF3 ; PLA ; PULL RETURN STA 00 PLA STA 01 ; PLA ; PULL DUMMY SINCE THIS IS A FUNCTION PLA PLA PLA ; LDY #07 ; SHIFT SOME BITS 7 TIMES L5CCC ASL 0BFF0 PHP ROL 0BFF1 ROL 0BFF2 ROL 0BFF3 BMI L5CE0 PLP BPL L5CE6 BMI L5CE3 L5CE0 PLP BMI L5CE6 L5CE3 INC 0BFF0 L5CE6 DEY BNE L5CCC ; PERFORMED 7 SHIFTS YET? NO, L5CCC. ; ; YES LDA 0BFF0 ; HIGH 16 BITS LSR A ; CLEAR HIGH BIT (ENSURES ONLY POSITIVE NUMBER RETURNED) PHA ; LDA 0BFF2 ; USE $BFF2 AS PART OF RANDOM NUMBER LOW 16 BITS PHA ; LDA 01 ; PUSH RETURN PHA LDA 00 PHA RTS .END Final compiled file names: WIZARDRY.CODE Destination disk: All Wizardry Proving Grounds boot and scenario disks. Release #: WC054 - Release 18 Mar 2026 v3.2 ================================================ Status: Fixed. Recompiled. Verified. Date of change: 18-Mar-2026. Contributors: Eric Labelle, Peter Ferrie (Qkumba), 4am. Compiled by: Eric Labelle. Enhancements: Fully recompiled release v3.2 as of 18 Mar 2026. This release includes the following fixes and improvements since release 3.1: - Game Q)uick Plot option now makes the screen draw faster when there are poisoned characters. - New fonts by 4am. My grateful thanks to 4am for this marvelous work. - Added a pause after stepping on a CHUTE! square to see that it happened at higher speeds. - Game breaker fix for after getting out of a FIZZLE square the spells fizzling effect now stops. - Fix the Random Number Generator and have assembly code to now use safe memory locations by Qkumba. My grateful thanks to Qkumba for this incredible feat. Consistency: The Pascal disk volume names for the boot and scenario disks have been updated to WBV3.2: and WSV3.2: Following are the programming code details ========================================== Source disk: Wiz1E.dsk File: OPTIONS.TEXT Procedure: SEGMENT PROCEDURE OPTIONS; (* P070301 *) Code from: WRITE( ' VERSION 3.1 OF 24-MAR-2024 SER:'); Code to: (* VERSION DATE : 18-MAR-2026 WC054 *) (* ENHANCEMENTS AND FIXES : ST001 ST003 ST004 WC041 *) (* ACKWNOLEDGEMENTS FOR VERSION 3.2 *) (* THOMAS W. EWERS - WIZARDRY PASCAL AND ASSEMBLY CODE REVERSE-ENGINEERING *) (* ERIC LABELLE (SNAFARU) - DATABASE FIXES. ENGINE FIXES, ENHANCEMENTS, *) (* AND QUALITY OF LIFE IMPROVEMENTS. RE-COMPILING. VERSION 3.2 RELEASE *) (* PETER FERRIE (QKUMBA) - PRODOS SUPPORT, SAFE MEMORY LOCATION AND FIX *) (* FOR THE RANDOM NUMBER GENERATOR. *) (* 4AM - FONTS *) (* CHRIS TORRENCE (CT6502) - 40-COLUMNS FIX FOR APPLE IIE *) (* OTHER PEOPLE THAT HELPED SNAFARU ALONG THE WAY: STEVE EVANS, *) (* DENIS MOLONY (WIZARDRY APP), MARSHALL BOCKRATH, DDG AHAB, *) (* DAN GARTUNG (WIZARD'S WORKBENCH), AND THE AUTHOR(S) OF THE BIG M *) (* WIZARDRY SCENARIO EDITOR, AS WELL AS THE NUMEROUS FANS FOR THEIR *) (* SUGGESTIONS AND FEEDBACK *) (* *) (* SNAFARU *) . . . (* WC054 RELEASE DATE *) WRITE( ' VERSION 3.2 OF 18-MAR-2026 SER:'); Final compiled file names: SYSTEM.STARTUP Destination disk: Any Wizardry Proving Grounds boot disks.