neilobremski
Experienced Member
In Magenta's Maze the core of the puzzle is finding the roots of a polynomial equation. When I wrote the main game, I wasn't sure how far I'd take that so I made some generalized math functions that do this allowing for arbitrary amounts of terms, roots, etc. This is cool but makes it difficult to translate to assembly. Thankfully there is a certain amount of predictability such that I can simplify the algorithm.
The only roots allowed are 1 to 9 which, as terms, show as (x - ?) where the ? is the root. This limitation comes from the fact that there are only 9 cubes hidden in the forest maze of the game and none of them are duplicated. This always results in a polynomial to the third degree with only three values (two coefficients and one constant):
Calculating each of these is a cinch. Considering each root is A, B, and C:
X[SUP]2[/SUP] = -(A + B + C)
X = (A * B)(A * C)(B * C)
C = -(A * B * C)
Thankfully the only value that can be larger than 255 is the constant which, in the case of a triple 9 root, becomes 729. Thus we can safely pass the roots as byte values, store the coefficients in byte values (X[SUP]3[/SUP] is always 1 and so needs no storing), and only save the constant in a word. I coded this up in DEBUG using assembler whereby the caller passes roots A, B, and C as CL, DH, and DL respectively (lines up nicely in the register display):
You'll notice the signs of the terms are not kept, because I know it's always going to be negative, positive, negative when I display the polynomial in a string. The results are thus stored in AX (constant), BL (X coefficient), and CH (X[SUP]2[/SUP] coefficient).
This is a neat 32 bytes that becomes a sad 33 when RET is added. I can't help but love it when assembler routines fit tightly within paragraph boundaries. If only I could save one more byte ...
The only roots allowed are 1 to 9 which, as terms, show as (x - ?) where the ? is the root. This limitation comes from the fact that there are only 9 cubes hidden in the forest maze of the game and none of them are duplicated. This always results in a polynomial to the third degree with only three values (two coefficients and one constant):
X[SUP]3[/SUP] - nX[SUP]2[/SUP] + nX - C
Calculating each of these is a cinch. Considering each root is A, B, and C:
X[SUP]2[/SUP] = -(A + B + C)
X = (A * B)(A * C)(B * C)
C = -(A * B * C)
Thankfully the only value that can be larger than 255 is the constant which, in the case of a triple 9 root, becomes 729. Thus we can safely pass the roots as byte values, store the coefficients in byte values (X[SUP]3[/SUP] is always 1 and so needs no storing), and only save the constant in a word. I coded this up in DEBUG using assembler whereby the caller passes roots A, B, and C as CL, DH, and DL respectively (lines up nicely in the register display):
Code:
MOV CH, CL ; CH will be X^2 coefficient / start with root A
ADD CH, DH ; add root B to X^2 coefficient
ADD CH, DL ; add root C to X^2 coefficient (finished)
MOV AL, CL ; load root A in accumulator
MUL DH ; (A * B)
MOV BL, AL ; BL will be X coefficient / start with (A * B)
MOV AL, CL ; load root A in accumulator
MUL DL ; (A * C)
ADD BL, AL ; add (A * C) to X coefficient
MOV AL, DH ; load root B in accumulator
MUL DL ; (B * C)
ADD BL, AL ; add (B * C) to X coefficient (finished)
XOR AX, AX ; clear accumulator
MOV AL, CL ; AX will be constant / start with root A
MUL DH ; multiply root B by constant
MUL DL ; multiply root C by constant (finished)
You'll notice the signs of the terms are not kept, because I know it's always going to be negative, positive, negative when I display the polynomial in a string. The results are thus stored in AX (constant), BL (X coefficient), and CH (X[SUP]2[/SUP] coefficient).
This is a neat 32 bytes that becomes a sad 33 when RET is added. I can't help but love it when assembler routines fit tightly within paragraph boundaries. If only I could save one more byte ...