CONST Skyblue~&
= &HFF87CEEB CONST Gold~&
= &HFFFFD700 CONST Black~&
= &HFF000000 CONST LightGray~&
= &HFFD3D3D3
Set_OrderOfOperations 'This will also make certain our directories are valid, and if not make them.
choices
AS INTEGER 'from 0 to choices, so subtract 1 from total number of choices captions
AS STRING ' "12345678901234567890" --10 spaces per choice, so the left would represent two choices clicks
AS INTEGER 'binary value of click state for our choices; up to 16 max
Options(1).x = 70: Options(1).y = 100: Options(1).high = 50: Options(1).wide = 100 '1 is mode
Options(1).choices = 4: Options(1).captions = "+ - * / RND "
Options(1).Font = F25: Options(1).clicks = 16 'rnd selected as default
Options(2).x = 70: Options(2).y = 200: Options(2).high = 50: Options(2).wide = 100 '2 is time
Options(2).choices = 4: Options(2).captions = "15 30 60 120 300 "
Options(2).Font = F25: Options(2).clicks = 4 '60 second default game
Options(3).x = 70: Options(3).y = 300: Options(3).high = 50: Options(3).wide = 100 '3 is difficulty
Options(3).choices = 4:: Options(3).captions = "TRIVIAL EASY AVERAGE HARD INSANE "
Options(3).Font = F15: Options(3).clicks = 4 'average default setting
SetupOptions
PlayGame
oldmouse = -1: oldmouse2 = -1
s = SaveState
ProblemsSolved = 0
RedoDivisionByZero:
num1
= RND * Highnum
+ LowNum
num2
= RND * Highnum
+ LowNum
IF o$
= "/" THEN num1
= num1
* num2:
IF num2
= 0 GOTO RedoDivisionByZero
answer$ = Evaluate_Expression$(math$)
TimeLeft
= FinishTime
- TIMER BoxTitle
45 + i
* 110, 240, 110, 100, 3, &HFF0FFF00, Gold
, _TRIM$(STR$(i
)) BoxTitle
45 + i
* 110, 340, 110, 100, 3, &HFF0FFF00, Gold
, _TRIM$(STR$(i
+ 5))
Choice = Xclick + 5 * Yclick
g = g + 1
display$ = math$ + "=" + guess$
COLOR &HFFFF0000, 0: BoxTitle
45, 100, 550, 100, 3, Skyblue
, Gold
, display$
ProblemsSolved = ProblemsSolved + 1
Problem(ProblemsSolved) = math$
Answer(ProblemsSolved) = answer$
Guess(ProblemsSolved) = guess$
FinishTime = FinishTime + 1 '1 second extra time for each correct answer
FinishTime = FinishTime - 1 'and a 1 second penalty for a wrong answer
TimeLeft
= FinishTime
- TIMER
i = 1
i = i + 1
Mousepause
RestoreState s
PRINT "Click <Left Button> for more results" click = 0
click = -1
s = SaveState
FOR i
= 1 TO 3 '3 option sets to display x1 = Options(i).x: y1 = Options(i).y
w = Options(i).wide: H = Options(i).high
clicks = Options(i).clicks
FOR j
= 0 TO Options
(i
).choices
t$
= _TRIM$(MID$(Options
(i
).captions
, j
* 10, 10)) COLOR Black
, 0: BoxTitle x1
+ j
* w
, y1
, w
, H
, 3, Skyblue
, Gold
, t$
COLOR LightGray
, 0: BoxTitle x1
+ j
* w
, y1
, w
, H
, 3, Black
, Gold
, t$
CenterText 0, 0, 640, 100, "Math Flash!"
BoxTitle 170, 390, 300, 60, 3, &HFF0FFF00, Gold, "PLAY"
IF ClickX
>= 0 AND ClickX
<= 4 THEN 'Click on menu item 0 to 4 SELECT CASE ClickY
'1 = top , 3 = middle, 5 = bottom IF Options
(1).clicks
AND 16 THEN Options
(1).clicks
= 0 ELSE Options
(1).clicks
= 16 Options
(1).clicks
= Options
(1).clicks
XOR 2 ^ ClickX
IF Options
(1).clicks
<> 16 THEN Options
(1).clicks
= Options
(1).clicks
AND NOT 16 Options(ClickY \ 2 + 1).clicks = 2 ^ ClickX
opt$ = ""
IF Options
(1).clicks
= 16 THEN Options
(1).clicks
= INT(RND * 15) + 1 IF Options
(1).clicks
AND 1 THEN opt$
= opt$
+ "+" IF Options
(1).clicks
AND 2 THEN opt$
= opt$
+ "-" IF Options
(1).clicks
AND 4 THEN opt$
= opt$
+ "/" IF Options
(1).clicks
AND 8 THEN opt$
= opt$
+ "*" CASE 1: LowNum
= 1: Highnum
= 5 CASE 2: LowNum
= 0: Highnum
= 10 CASE 4: LowNum
= 0: Highnum
= 12 CASE 8: LowNum
= 0: Highnum
= 99 CASE 16: LowNum
= 10: Highnum
= 89 RestoreState s
Box x1, y1, x2, y2, thick, fg, bg
CenterText x1, y1 + thick, x1 + x2, y1 + y2 + thick, title$
LINE (x
+ thick
, y
+ thick
)-STEP(wide
- 2 * thick
, high
- 2 * thick
), Kolor
, BF
SUB CenterText
(x1
, y1
, x2
, y2
, text$
) xmax = x2 - x1: ymax = y2 - y1
xpos = (xmax - textlength) / 2
DIM SS
AS SaveStateType
, Temp
AS SaveStateType
SaveMem
= _MEMNEW(LEN(SS
) * 255) 'Save up to 255 save states; More than 255 and we toss an error
'Data to Save
SS.InUse = -1
_MEMGET SaveMem
, SaveMem.OFFSET
+ O
, Temp
_MEMPUT SaveMem
, SaveMem.OFFSET
+ O
, SS
SaveState = i
_MEMPUT SaveMem
, SaveMem.OFFSET
+ NSS
* LEN(SS
), SS
NSS = NSS + 1
SaveState = NSS
_MEMGET SaveMem
, SaveMem.OFFSET
+ (WhichOne
- 1) * LEN(SS
), SS
SS.InUse = 0 'Let the routine know that we're no longer in use for this handle
_MEMPUT SaveMem
, SaveMem.OFFSET
+ (WhichOne
- 1) * LEN(SS
), SS
t$ = e$ 'So we preserve our original data, we parse a temp copy of it
b
= INSTR(UCASE$(e$
), "EQL") 'take out assignment before the preparser sees it
QuickReturn = 0
PreParse t$
'Deal with brackets first
exp$
= "(" + t$
+ ")" 'Starting and finishing brackets for our parse routine.
c = 0
c = c + 1
s = Eval_E - c + 1
eval$
= " " + MID$(exp$
, s
, Eval_E
- s
) + " " 'pad with a space before and after so the parser can pick up the values properly. ParseExpression eval$
temppp$
= DWD
(LEFT$(exp$
, s
- 2) + " ## " + eval$
+ " ## " + MID$(exp$
, E
+ 1)) c = 0
c = c + 1
CASE "0" TO "9", ".", "-" 'At this point, we should only have number values left.
Evaluate_Expression$
= exp$
'We should now have an expression with no () to deal with
lowest = 0
'Look for first valid operator
IF J
= PL
(P
) THEN 'Priority levels match IF op
> 0 AND op
< lowest
THEN lowest
= op: OpOn
= P
IF OpOn
= 0 THEN EXIT DO 'We haven't gotten to the proper PL for this OP to be processed yet. numset = 0
'*** SPECIAL OPERATION RULESETS
IF OName
(OpOn
) = "-" THEN 'check for BOOLEAN operators before the - CASE "NOT", "XOR", "AND", "EQV", "IMP" EXIT DO 'Not an operator, it's a negative
CASE "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "N": numset
= -1 'Valid digit CASE "-" 'We need to check if it's a minus or a negative CASE ELSE 'Not a valid digit, we found our separator c = c + 1
E = op + c
c = 0
c = c + 1
CASE "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "N" 'Valid digit CASE "-" 'We need to check if it's a minus or a negative c1 = c
bad = 0
c1 = c1 + 1
CASE "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "." bad = -1
'It's a negative sign and needs to count as part of our numbers
CASE ELSE 'Not a valid digit, we found our separator s = op - c
num
(1) = MID$(exp$
, s
+ 1, op
- s
- 1) 'Get our first number num
(2) = MID$(exp$
, op
+ LEN(OName
(OpOn
)), E
- op
- LEN(OName
(OpOn
)) + 1) 'Get our second number num(3) = EvaluateNumbers(OpOn, num())
'PRINT "*************"
'PRINT num(1), OName(OpOn), num(2), num(3), exp$
'PRINT exp$
op = 0
SUB Set_OrderOfOperations
'PL sets our priortity level. 1 is highest to 65535 for the lowest.
'I used a range here so I could add in new priority levels as needed.
'OName ended up becoming the name of our commands, as I modified things.... Go figure! LOL!
'Constants get evaluated first, with a Priority Level of 1
'I'm not certain where exactly percentages should go. They kind of seem like a special case to me. COS10% should be COS.1 I'd think...
'I'm putting it here for now, and if anyone knows someplace better for it in our order of operations, let me know.
'Then Functions with PL 10
'Exponents with PL 20
'Multiplication and Division PL 30
'Integer Division PL 40
'MOD PL 50
'Addition and Subtraction PL 60
'Relational Operators =, >, <, <>, <=, >= PL 70
i
= i
+ 1:
REDIM _PRESERVE OName
(i
): OName
(i
) = "><" 'These next three are just reversed symbols as an attempt to help process a common typo i
= i
+ 1:
REDIM _PRESERVE OName
(i
): OName
(i
) = "=<" 'I personally can never keep these things straight. Is it < = or = <... i
= i
+ 1:
REDIM _PRESERVE OName
(i
): OName
(i
) = "=>" 'Who knows, check both! 'Logical Operations PL 80+
CASE "_PI": n1
= 3.14159265358979323846264338327950288##
'Future compatable in case something ever stores extra digits for PI CASE "%": n1
= (VAL(num
(1))) / 100 'Note percent is a special case and works with the number BEFORE the % command and not after CASE "_D2R": n1
= 0.0174532925 * (VAL(num
(2))) CASE "_D2G": n1
= 1.1111111111 * (VAL(num
(2))) CASE "_R2D": n1
= 57.2957795 * (VAL(num
(2))) CASE "_R2G": n1
= 0.015707963 * (VAL(num
(2))) CASE "_G2D": n1
= 0.9 * (VAL(num
(2))) CASE "_G2R": n1
= 63.661977237 * (VAL(num
(2))) n1
= VAL(num
(1)): n2
= VAL(num
(2)) n3 = 1## / n2
n1 = sign * (n1 ^ n3)
n1
= VAL(num
(1)) \
VAL(num
(2)) EvaluateNumbers$ = "ERROR - Bad operation (We shouldn't see this)"
EvaluateNumbers$ = "ERROR - Bad operation (We shouldn't see this)" 'Let's say we're bad...
'To deal with duplicate operators in our code.
'Such as -- becomes a +
'++ becomes a +
'+- becomes a -
'-+ becomes a -
bad = 0
DWD$ = t$
VerifyString t$
t$ = e$
'First strip all spaces
t$ = ""
IF t$
= "" THEN e$
= "ERROR -- NULL string; nothing to evaluate":
EXIT SUB
'ERROR CHECK by counting our brackets
l = 0
l = 0
'Modify so that NOT will process properly
l = 0
l
= INSTR(l
+ 1, t$
, "NOT") 'We need to work magic on the statement so it looks pretty.
' 1 + NOT 2 + 1 is actually processed as 1 + (NOT 2 + 1)
'Look for something not proper
l1
= INSTR(l
+ 1, t$
, "AND") t$
= LEFT$(t$
, l
- 1) + "(" + MID$(t$
, l
, l1
- l
) + ")" + MID$(t$
, l
+ l1
- l
) l = l + 3
'PRINT t$
'Check for bad operators before a ( bracket
l = 0
l
= INSTR(l
+ 1, t$
, "(") IF l
AND l
> 2 THEN 'Don't check the starting bracket; there's nothing before it. good = 0
IF MID$(t$
, l
- LEN(OName
(i
)), LEN(OName
(i
))) = OName
(i
) AND PL
(i
) > 1 AND PL
(i
) <= 250 THEN good
= -1:
EXIT FOR 'We found an operator after our ), and it's not a CONST (like PI) l = l + 1
'Check for bad operators after a ) bracket
l = 0
l
= INSTR(l
+ 1, t$
, ")") good = 0
IF MID$(t$
, l
+ 1, LEN(OName
(i
))) = OName
(i
) AND PL
(i
) > 1 AND PL
(i
) <= 250 THEN good
= -1:
EXIT FOR 'We found an operator after our ), and it's not a CONST (like PI) l = l + 1
'Turn all &H (hex) numbers into decimal values for the program to process properly
l = 0
E = l + 1: finished = 0
E = E + 1
CASE "0" TO "9", "A" TO "F" 'All is good, our next digit is a number, continue to add to the hex$ good = 0
IF MID$(t$
, E
, LEN(OName
(i
))) = OName
(i
) AND PL
(i
) > 1 AND PL
(i
) <= 250 THEN good
= -1:
EXIT FOR 'We found an operator after our ), and it's not a CONST (like PI) E = E - 1
finished = -1
'Turn all &B (binary) numbers into decimal values for the program to process properly
l = 0
E = l + 1: finished = 0
E = E + 1
CASE "0", "1" 'All is good, our next digit is a number, continue to add to the hex$ good = 0
IF MID$(t$
, E
, LEN(OName
(i
))) = OName
(i
) AND PL
(i
) > 1 AND PL
(i
) <= 250 THEN good
= -1:
EXIT FOR 'We found an operator after our ), and it's not a CONST (like PI) E = E - 1
finished = -1
bin$
= MID$(t$
, l
+ 2, E
- l
- 1)
t$ = N2S(t$)
VerifyString t$
e$ = t$
'ERROR CHECK for unrecognized operations
j = 1
CASE "0" TO "9", ".", "(", ")": j
= j
+ 1 good = 0
IF MID$(t$
, j
, LEN(OName
(i
))) = OName
(i
) THEN good
= -1:
EXIT FOR 'We found an operator after our ), and it's not a CONST (like PI) IF NOT good
THEN t$
= "ERROR - Bad Operational value. (" + comp$
+ ")":
EXIT SUB
IF check1
< 1 OR check1
> 1 THEN N2S
= exp$:
EXIT SUB 'If no scientic notation is found, or if we find more than 1 type, it's not SN!
SELECT CASE l
'l now tells us where the SN starts at.
l$
= LEFT$(t$
, l
- 1) 'The left of the SN r$
= MID$(t$
, l
+ 1): r&&
= VAL(r$
) 'The right of the SN, turned into a workable long
IF INSTR(l$
, ".") THEN 'Location of the decimal, if any r&& = r&& + 1
CASE 0 'what the heck? We solved it already? 'l$ = l$
l$ = "0" + l$
l$ = "0." + l$
l$ = l$ + "0"
N2S$ = sign$ + l$