From 3b51ec61b413448b0b4f079e3712b36f992c7e67 Mon Sep 17 00:00:00 2001 From: William Barnes Date: Sun, 29 May 2022 02:06:31 -0400 Subject: [PATCH] Refined implementation of RND, Randomize. --- codemirror/qb-lang.js | 2 +- qb.js | 25 +++++++++++++++++++++- qb2js.js | 49 ++++++++++++++++++++++++++++++------------- tools/qb2js.bas | 44 +++++++++++++++++++++++++++----------- 4 files changed, 92 insertions(+), 28 deletions(-) diff --git a/codemirror/qb-lang.js b/codemirror/qb-lang.js index 294737e..17d34a1 100644 --- a/codemirror/qb-lang.js +++ b/codemirror/qb-lang.js @@ -42,7 +42,7 @@ CodeMirror.defineMode("qbjs", function(conf, parserConf) { '_screenexists', '_sinh', '_source', '_sndclose', '_sndopen', '_sndplay', '_sndloop', '_sndpause', '_sndstop', '_sndvol', '_title', '_trim', '_width', 'abs', 'asc', 'atn', 'beep', 'chr', 'circle', 'cls', 'color', 'command', 'cos', 'cvi', 'cvl', 'data', 'draw', 'exp', 'fix', 'hex', 'input', 'inkey', 'instr', 'int', 'lbound', 'left', 'lcase', 'len', 'line', 'locate', 'log', 'ltrim', 'mid', 'mki', 'mkl', - 'oct', 'paint', 'point', 'preset', 'print', 'pset', 'right', 'rtrim', 'read', 'restore', 'rnd', 'screen', 'shared', 'sgn', 'sin', 'sleep', 'space', 'sqr', + 'oct', 'paint', 'point', 'preset', 'print', 'pset', 'right', 'rtrim', 'randomize', 'read', 'restore', 'rnd', 'screen', 'shared', 'sgn', 'sin', 'sleep', 'space', 'sqr', 'str', 'swap', 'tan', 'time', 'timer', 'ubound', 'ucase', 'val', 'varptr', 'window', // QBJS-specific 'export', 'from', 'import', '_label'] diff --git a/qb.js b/qb.js index 16de588..6ef8bf7 100644 --- a/qb.js +++ b/qb.js @@ -39,6 +39,7 @@ var QB = new function() { var _dataBulk = []; var _readCursorPosition; var _dataLabelMap = new Map(); + var _randomSeed = 327680; // Array handling methods // ---------------------------------------------------- @@ -1630,9 +1631,31 @@ var QB = new function() { return String(value).trimEnd(); } + this.sub_Randomize = function(using, n) { + const buffer = new ArrayBuffer(8); + const view = new DataView(buffer); + var m; + if (n == undefined) { + view.setFloat64(0, 0, false); // TODO: implement prompt + m = view.getUint32(0); + m ^= (m >> 16); + _randomSeed = ((m & 0xffff)<<8) | (_randomSeed & 0xff); + } else { + view.setFloat64(0, n, false); + m = view.getUint32(0); + m ^= (m >> 16); + if (using == false) { + _randomSeed = ((m & 0xffff)<<8) | (_randomSeed & 0xff); + } else if (using == true) { + _randomSeed = ((m & 0xffff)<<8) | (327680 & 0xff); + } + } + } + this.func_Rnd = function(n) { // TODO: implement modifier parameter - return Math.random(); + _randomSeed = (_randomSeed * 16598013 + 12820163) & 0xFFFFFF; + return _randomSeed / 0x1000000; // Inspired by libqb.cpp. } this.sub_Screen = async function(mode) { diff --git a/qb2js.js b/qb2js.js index 4d729ef..e6f77fd 100644 --- a/qb2js.js +++ b/qb2js.js @@ -506,26 +506,28 @@ var ConvertSub = null; } if ( m.name == "Line" ) { js = (await func_CallMethod( m)) +"(" +(await func_ConvertLine( args)) +");"; - } else if ( m.name == "PSet" || m.name == "Circle" || m.name == "PReset" || m.name == "Paint" ) { - js = (await func_CallMethod( m)) +"(" +(await func_ConvertPSet( args)) +");"; - } else if ( m.name == "_PrintString" ) { - js = (await func_CallMethod( m)) +"(" +(await func_ConvertPrintString( args)) +");"; - } else if ( m.name == "Print" ) { - js = (await func_CallMethod( m)) +"(" +(await func_ConvertPrint( args)) +");"; - } else if ( m.name == "Input" || m.name == "Line Input" ) { - js = (await func_ConvertInput( m, args)); - } else if ( m.name == "Read" ) { - js = (await func_ConvertRead( m, args)); - } else if ( m.name == "Swap" ) { - js = (await func_ConvertSwap( m, args)); } else if ( m.name == "Cls" ) { js = (await func_CallMethod( m)) +"(" +(await func_ConvertCls( args)) +");"; } else if ( m.name == "Data" ) { js = (await func_CallMethod( m)) +"(" +(await func_ConvertData( args)) +");"; - } else if ( m.name == "_PutImage" ) { - js = (await func_CallMethod( m)) +"(" +(await func_ConvertPutImage( args)) +");"; + } else if ( m.name == "Input" || m.name == "Line Input" ) { + js = (await func_ConvertInput( m, args)); + } else if ( m.name == "PSet" || m.name == "Circle" || m.name == "PReset" || m.name == "Paint" ) { + js = (await func_CallMethod( m)) +"(" +(await func_ConvertPSet( args)) +");"; + } else if ( m.name == "Print" ) { + js = (await func_CallMethod( m)) +"(" +(await func_ConvertPrint( args)) +");"; + } else if ( m.name == "Randomize" ) { + js = (await func_ConvertRandomize( m, args)); + } else if ( m.name == "Read" ) { + js = (await func_ConvertRead( m, args)); + } else if ( m.name == "Swap" ) { + js = (await func_ConvertSwap( m, args)); } else if ( m.name == "Window" ) { js = (await func_CallMethod( m)) +"(" +(await func_ConvertWindow( args)) +");"; + } else if ( m.name == "_PrintString" ) { + js = (await func_CallMethod( m)) +"(" +(await func_ConvertPrintString( args)) +");"; + } else if ( m.name == "_PutImage" ) { + js = (await func_CallMethod( m)) +"(" +(await func_ConvertPutImage( args)) +");"; } else if ( m.name == "_FullScreen" ) { js = (await func_CallMethod( m)) +"(" +(await func_ConvertFullScreen( args)) +");"; } else { @@ -760,6 +762,24 @@ var ConvertData = null; ConvertData = r +"]"; return ConvertData; } +async function func_ConvertRandomize(m/*METHOD*/,args/*STRING*/) { +if (QB.halted()) { return; } +var ConvertRandomize = null; + var uusing = ''; // STRING + var theseed = ''; // STRING + uusing = "false"; + theseed = args; + if ((QB.func__Trim( args)) == "" ) { + theseed = "undefined"; + } else { + if (((QB.func_UCase( (QB.func__Trim( (QB.func_Left( args, 5)))))) == "USING") ) { + uusing = "true"; + theseed = (QB.func__Trim( (QB.func_Right( args, (QB.func_Len( args)) - 5)))); + } + } + ConvertRandomize = (await func_CallMethod( m)) +"(" + uusing +", " + theseed +")"; +return ConvertRandomize; +} async function func_ConvertRead(m/*METHOD*/,args/*STRING*/) { if (QB.halted()) { return; } var ConvertRead = null; @@ -2867,6 +2887,7 @@ if (QB.halted()) { return; } await sub_AddQBMethod( "SUB", "PReset", False); await sub_AddQBMethod( "SUB", "Print", True); await sub_AddQBMethod( "SUB", "PSet", False); + await sub_AddQBMethod( "SUB", "Randomize", False); await sub_AddQBMethod( "SUB", "Restore", False); await sub_AddQBMethod( "FUNCTION", "Right$", False); await sub_AddQBMethod( "FUNCTION", "RTrim$", False); diff --git a/tools/qb2js.bas b/tools/qb2js.bas index 5daeed5..488ec83 100644 --- a/tools/qb2js.bas +++ b/tools/qb2js.bas @@ -591,17 +591,23 @@ Function ConvertSub$ (m As Method, args As String) If m.name = "Line" Then js = CallMethod(m) + "(" + ConvertLine(args) + ");" + ElseIf m.name = "Cls" Then + js = CallMethod(m) + "(" + ConvertCls(args) + ");" + + ElseIf m.name = "Data" Then + js = CallMethod(m) + "(" + ConvertData(args) + ");" + + ElseIf m.name = "Input" Or m.name = "Line Input" Then + js = ConvertInput(m, args) + ElseIf m.name = "PSet" Or m.name = "Circle" Or m.name = "PReset" Or m.name = "Paint" Then js = CallMethod(m) + "(" + ConvertPSet(args) + ");" - ElseIf m.name = "_PrintString" Then - js = CallMethod(m) + "(" + ConvertPrintString(args) + ");" - ElseIf m.name = "Print" Then js = CallMethod(m) + "(" + ConvertPrint(args) + ");" - ElseIf m.name = "Input" Or m.name = "Line Input" Then - js = ConvertInput(m, args) + ElseIf m.name = "Randomize" Then + js = ConvertRandomize(m, args) ElseIf m.name = "Read" Then js = ConvertRead(m, args) @@ -609,18 +615,15 @@ Function ConvertSub$ (m As Method, args As String) ElseIf m.name = "Swap" Then js = ConvertSwap(m, args) - ElseIf m.name = "Cls" Then - js = CallMethod(m) + "(" + ConvertCls(args) + ");" + ElseIf m.name = "Window" Then + js = CallMethod(m) + "(" + ConvertWindow(args) + ");" - ElseIf m.name = "Data" Then - js = CallMethod(m) + "(" + ConvertData(args) + ");" + ElseIf m.name = "_PrintString" Then + js = CallMethod(m) + "(" + ConvertPrintString(args) + ");" ElseIf m.name = "_PutImage" Then js = CallMethod(m) + "(" + ConvertPutImage(args) + ");" - ElseIf m.name = "Window" Then - js = CallMethod(m) + "(" + ConvertWindow(args) + ");" - ElseIf m.name = "_FullScreen" Then js = CallMethod(m) + "(" + ConvertFullScreen(args) + ");" Else @@ -836,6 +839,22 @@ Function ConvertData$ (args As String) ConvertData$ = r + "]" End Function +Function ConvertRandomize$ (m As Method, args As String) + Dim uusing As String + Dim theseed As String + uusing = "false" + theseed = args + If _Trim$(args) = "" Then + theseed = "undefined" + Else + If (UCase$(_Trim$(Left$(args, 5))) = "USING") Then + uusing = "true" + theseed = _Trim$(Right$(args, Len(args) - 5)) + End If + End If + ConvertRandomize = CallMethod(m) + "(" + uusing + ", " + theseed + ")" +End Function + Function ConvertRead$ (m As Method, args As String) Dim js As String Dim vname As String @@ -2992,6 +3011,7 @@ Sub InitQBMethods AddQBMethod "SUB", "PReset", False AddQBMethod "SUB", "Print", True AddQBMethod "SUB", "PSet", False + AddQBMethod "SUB", "Randomize", False AddQBMethod "SUB", "Restore", False AddQBMethod "FUNCTION", "Right$", False AddQBMethod "FUNCTION", "RTrim$", False