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.
