• Please review our updated Terms and Rules here

Generating Polynomials

neilobremski

Experienced Member
Joined
Oct 9, 2016
Messages
55
Location
Seattle, USA
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):

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 ...
 
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 ...

You can save one more byte since the value passed in CL is always less than 128. Replace this;
Code:
XOR AX, AX	; clear accumulator
MOV AL, CL	; AX will be constant / start with root A
with this;
Code:
MOV AL, CL
CBW

EDIT: Actually, since you are only multiplying with byte values you can skip the CBW.
 
Back
Top