Add C alternatives for generateLevel and random functions but keep the javascript ones for the emulator + put certain functions always in ram

pull/3021/head
Willems Davy 2023-09-15 04:18:40 +02:00
parent 6d47b4d994
commit 003a307280
1 changed files with 284 additions and 93 deletions

View File

@ -200,12 +200,162 @@ const TITLE = {
}; };
// -------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------
// C Code
//
// random stuff // random stuff
// https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript#72732727 // https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript#72732727
// https://www.ams.org/journals/mcom/1999-68-225/S0025-5718-99-00996-5/S0025-5718-99-00996-5.pdf
//
// power2 function
// https://www.geeksforgeeks.org/write-a-c-program-to-calculate-powxn/
// -------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------
//this will give an uncaught exception in emulator
//but code will still run fine as i'll run javascript versions then
var c = E.compiledC(`
//void srand(int)
//int random(int)
//void generateLevel(int,int,int)
unsigned int m;
unsigned int a;
unsigned int s;
int power2 (int x, unsigned int y)
{
int temp;
if (y == 0)
return 1;
temp = power2 (x, y / 2);
if ((y % 2) == 0)
return temp * temp;
else
return x * temp * temp;
}
void srand(int seed)
{
m = power2(2, 16) - 15;
a = 33285;
s = seed % m;
}
int random(int value)
{
s = s * a % m;
return s % value;
}
void generateLevel(unsigned char* level, int boardWidth, int boardHeight ) {
int cc = 0;
int currentPoint = 0;
int visitedRooms = 1;
int tmp, tmp2;
int selectedNeighbour;
int neighboursFound;
int lookUpX, lookUpY;
int rnd;
int neighbours[4];
int cellStack[(boardWidth*boardHeight) +1];
//intial all walls value in every room we will remove bits of this value to remove walls
for (int i = 0; i < boardWidth*boardHeight; i++)
level[i] = 0xf;
while (visitedRooms != boardWidth * boardHeight) {
neighboursFound = 0;
lookUpX = currentPoint % boardWidth;
lookUpY = (currentPoint / boardWidth) | 0;
tmp = currentPoint + 1;
//tile has neighbour to the right which we did not handle yet
if ((lookUpX + 1 < boardWidth) && (level[tmp] == 0xf))
neighbours[neighboursFound++] = tmp;
tmp = currentPoint - 1;
//tile has neighbour to the left which we did not handle yet
if ((lookUpX > 0) && (level[tmp] == 0xf))
neighbours[neighboursFound++] = tmp;
tmp = currentPoint - boardWidth;
//tile has neighbour the north which we did not handle yet
if ((lookUpY > 0) && (level[tmp] == 0xf))
neighbours[neighboursFound++] = tmp;
tmp = currentPoint + boardWidth;
//tile has neighbour the south which we did not handle yet
if ((lookUpY + 1 < boardHeight) && (level[tmp] == 0xf))
neighbours[neighboursFound++] = tmp;
if (neighboursFound == 0)
{
currentPoint = cellStack[--cc];
continue;
} else {
rnd = random(neighboursFound);
}
selectedNeighbour = neighbours[rnd];
tmp = (selectedNeighbour % boardWidth);
//tile has neighbour to the east
if (tmp > lookUpX) {
//remove west wall neighbour
level[selectedNeighbour] &= ~(8);
//remove east wall tile
level[currentPoint] &= ~(2);
} else {
// tile has neighbour to the west
if (tmp < lookUpX) {
//remove east wall neighbour
level[selectedNeighbour] &= ~(2);
//remove west wall tile
level[currentPoint] &= ~(8);
} else {
// tile has neighbour to the north
tmp2 = selectedNeighbour / boardWidth;
if (tmp2 < lookUpY) {
//remove south wall neighbour
level[selectedNeighbour] &= ~(4);
//remove north wall tile
level[currentPoint] &= ~(1);
} else {
// tile has neighbour to the south
if (tmp2 > lookUpY) {
//remove north wall neighbour
level[selectedNeighbour] &= ~(1);
//remove south wall tile
level[currentPoint] &= ~(4);
}
}
}
}
//add tile to the cellstack
if (neighboursFound > 1) {
cellStack[cc++] = currentPoint;
}
//set tile to the neighbour
currentPoint = selectedNeighbour;
visitedRooms++;
}
}`);
//when using C Code it will generate levels
//a lot faster on the device.
//levels generated by the C Code are not the same
//as levels generated by the JS Code!
const USECCODE = c !== undefined;
print("Using C Code:" + USECCODE.toString());
// --------------------------------------------------------------------------------------------------
// random stuff
// --------------------------------------------------------------------------------------------------
let randfunc; let randfunc;
function srand(seed) { function srandjs(seed) {
var m = Math.pow(2, 35) - 31; var m = Math.pow(2, 35) - 31;
var a = 185852; var a = 185852;
var s = seed % m; var s = seed % m;
@ -214,10 +364,26 @@ function srand(seed) {
}; };
} }
function random(value) { function randomjs(value) {
return Math.floor(randfunc()) % value; return Math.floor(randfunc()) % value;
} }
function srand(seed) {
"RAM";
if(USECCODE)
c.srand(seed);
else
srandjs(seed);
}
function random(value) {
"RAM";
if(USECCODE)
return c.random(value);
else
return randomjs(value);
}
srand(Date().getTime()); srand(Date().getTime());
// -------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------
@ -323,6 +489,7 @@ function initCursors() {
// helper funcs // helper funcs
// -------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------
function set_bkg_tile_xy(x, y, tile) { function set_bkg_tile_xy(x, y, tile) {
"RAM";
g.drawImage(currentTiles, SCREENOFFSETX + x * TILESIZE, screenOffsetY + y * TILESIZE, { g.drawImage(currentTiles, SCREENOFFSETX + x * TILESIZE, screenOffsetY + y * TILESIZE, {
frame: tile frame: tile
}); });
@ -337,6 +504,7 @@ function get_bkg_data() {
} }
function set_bkg_tiles(x, y, map) { function set_bkg_tiles(x, y, map) {
"RAM";
g.drawImage(map, SCREENOFFSETX + x, screenOffsetY + y); g.drawImage(map, SCREENOFFSETX + x, screenOffsetY + y);
} }
@ -755,6 +923,116 @@ function intro() {
// -------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------
// Level Stuff // Level Stuff
// -------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------
function generateLeveljs() {
let neighbours = new Uint8Array(4);
let cellStack = [];//new Uint8Array(boardSize + 1);
let cc = 0;
let currentPoint = 0;
let visitedRooms = 1;
let tmp, tmp2;
let selectedNeighbour;
let neighboursFound;
let lookUpX, lookUpY;
let rnd;
//intial all walls value in every room we will remove bits of this value to remove walls
level.fill(0xf, 0, boardSize);
while (visitedRooms != boardSize) {
neighboursFound = 0;
lookUpX = currentPoint % boardWidth;
lookUpY = (currentPoint / boardWidth) | 0;
tmp = currentPoint + 1;
//tile has neighbour to the right which we did not handle yet
if ((lookUpX + 1 < boardWidth) && (level[tmp] == 0xf))
neighbours[neighboursFound++] = tmp;
tmp = currentPoint - 1;
//tile has neighbour to the left which we did not handle yet
if ((lookUpX > 0) && (level[tmp] == 0xf))
neighbours[neighboursFound++] = tmp;
tmp = currentPoint - boardWidth;
//tile has neighbour the north which we did not handle yet
if ((lookUpY > 0) && (level[tmp] == 0xf))
neighbours[neighboursFound++] = tmp;
tmp = currentPoint + boardWidth;
//tile has neighbour the south which we did not handle yet
if ((lookUpY + 1 < boardHeight) && (level[tmp] == 0xf))
neighbours[neighboursFound++] = tmp;
if (neighboursFound == 0)
{
currentPoint = cellStack[--cc];
continue;
} else {
rnd = random(neighboursFound);
}
selectedNeighbour = neighbours[rnd];
tmp = (selectedNeighbour % boardWidth);
//tile has neighbour to the east
if (tmp > lookUpX) {
//remove west wall neighbour
level[selectedNeighbour] &= ~(8);
//remove east wall tile
level[currentPoint] &= ~(2);
} else {
// tile has neighbour to the west
if (tmp < lookUpX) {
//remove east wall neighbour
level[selectedNeighbour] &= ~(2);
//remove west wall tile
level[currentPoint] &= ~(8);
} else {
// tile has neighbour to the north
tmp2 = selectedNeighbour / boardWidth;
if (tmp2 < lookUpY) {
//remove south wall neighbour
level[selectedNeighbour] &= ~(4);
//remove north wall tile
level[currentPoint] &= ~(1);
} else {
// tile has neighbour to the south
if (tmp2 > lookUpY) {
//remove north wall neighbour
level[selectedNeighbour] &= ~(1);
//remove south wall tile
level[currentPoint] &= ~(4);
}
}
}
}
//add tile to the cellstack
if (neighboursFound > 1) {
cellStack[cc++] = currentPoint;
}
//set tile to the neighbour
currentPoint = selectedNeighbour;
visitedRooms++;
}
}
function generateLevel()
{
"RAM";
if(USECCODE)
{
var cellstack = new Uint8Array(MAXBOARDSIZE + 1);
var neighbours = new Uint8Array(4);
var addrLevel = E.getAddressOf(level,true);
c.generateLevel(addrLevel, boardWidth, boardHeight);
}
else
{
generateLeveljs();
}
}
function moveBlockDown(aTile) { function moveBlockDown(aTile) {
let tmp = level[aTile + boardSize - boardWidth]; let tmp = level[aTile + boardSize - boardWidth];
for (let i = boardSize - boardWidth; i != 0; i -= boardWidth) for (let i = boardSize - boardWidth; i != 0; i -= boardWidth)
@ -1027,98 +1305,7 @@ function updateConnected() {
} }
} }
function generateLevel() {
let neighbours = new Uint8Array(4);
let cellStack = [];//new Uint8Array(boardSize + 1);
let cc = 0;
let currentPoint = 0;
let visitedRooms = 1;
let tmp, tmp2;
let selectedNeighbour;
let neighboursFound;
let lookUpX, lookUpY;
let rnd;
//intial all walls value in every room we will remove bits of this value to remove walls
level.fill(0xf, 0, boardSize);
while (visitedRooms != boardSize) {
neighboursFound = 0;
lookUpX = currentPoint % boardWidth;
lookUpY = (currentPoint / boardWidth) | 0;
tmp = currentPoint + 1;
//tile has neighbour to the right which we did not handle yet
if ((lookUpX + 1 < boardWidth) && (level[tmp] == 0xf))
neighbours[neighboursFound++] = tmp;
tmp = currentPoint - 1;
//tile has neighbour to the left which we did not handle yet
if ((lookUpX > 0) && (level[tmp] == 0xf))
neighbours[neighboursFound++] = tmp;
tmp = currentPoint - boardWidth;
//tile has neighbour the north which we did not handle yet
if ((lookUpY > 0) && (level[tmp] == 0xf))
neighbours[neighboursFound++] = tmp;
tmp = currentPoint + boardWidth;
//tile has neighbour the south which we did not handle yet
if ((lookUpY + 1 < boardHeight) && (level[tmp] == 0xf))
neighbours[neighboursFound++] = tmp;
if (neighboursFound == 0)
{
currentPoint = cellStack[--cc];
continue;
} else {
rnd = random(neighboursFound);
}
selectedNeighbour = neighbours[rnd];
tmp = (selectedNeighbour % boardWidth);
//tile has neighbour to the east
if (tmp > lookUpX) {
//remove west wall neighbour
level[selectedNeighbour] &= ~(8);
//remove east wall tile
level[currentPoint] &= ~(2);
} else {
// tile has neighbour to the west
if (tmp < lookUpX) {
//remove east wall neighbour
level[selectedNeighbour] &= ~(2);
//remove west wall tile
level[currentPoint] &= ~(8);
} else {
// tile has neighbour to the north
tmp2 = selectedNeighbour / boardWidth;
if (tmp2 < lookUpY) {
//remove south wall neighbour
level[selectedNeighbour] &= ~(4);
//remove north wall tile
level[currentPoint] &= ~(1);
} else {
// tile has neighbour to the south
if (tmp2 > lookUpY) {
//remove north wall neighbour
level[selectedNeighbour] &= ~(1);
//remove south wall tile
level[currentPoint] &= ~(4);
}
}
}
}
//add tile to the cellstack
if (neighboursFound > 1) {
cellStack[cc++] = currentPoint;
}
//set tile to the neighbour
currentPoint = selectedNeighbour;
visitedRooms++;
}
}
//when all board tiles are not below 16, the level is cleared //when all board tiles are not below 16, the level is cleared
//as there are 16 tiles per tilegroup (no water, water, special start with water) //as there are 16 tiles per tilegroup (no water, water, special start with water)
@ -1401,11 +1588,13 @@ function levelSelect() {
// printing functions // printing functions
// -------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------
function setCharAt(str, index, chr) { function setCharAt(str, index, chr) {
"RAM";
if (index > str.length - 1) return str; if (index > str.length - 1) return str;
return str.substring(0, index) + chr + str.substring(index + 1); return str.substring(0, index) + chr + str.substring(index + 1);
} }
function formatInteger(valinteger) { function formatInteger(valinteger) {
"RAM";
const maxDigits = 10; const maxDigits = 10;
let array = " "; let array = " ";
@ -1440,6 +1629,7 @@ function formatInteger(valinteger) {
//print a number on levelselect or game screen //print a number on levelselect or game screen
function printNumber(ax, ay, aNumber, maxDigits) { function printNumber(ax, ay, aNumber, maxDigits) {
"RAM";
const buffSize = 10; const buffSize = 10;
let ret = formatInteger(aNumber); let ret = formatInteger(aNumber);
@ -1455,6 +1645,7 @@ function printNumber(ax, ay, aNumber, maxDigits) {
//print a message on the title screen on ax,ay, the tileset from titlescreen contains an alphabet //print a message on the title screen on ax,ay, the tileset from titlescreen contains an alphabet
function printMessage(ax, ay, amsg) { function printMessage(ax, ay, amsg) {
"RAM";
let aCode = 'A'.charCodeAt(0); let aCode = 'A'.charCodeAt(0);
let zCode = 'Z'.charCodeAt(0); let zCode = 'Z'.charCodeAt(0);
let zeroCode = '0'.charCodeAt(0); let zeroCode = '0'.charCodeAt(0);