Random "Path" Generation Code - wolfram-mathematica
I am currently working on generating a random path for a game I am recreating. It is based off of the "Thin Ice" game in Club Penguin where you play as a fire character, walk across a path of ice, and get to the exit, melting as many ice blocks as possible along the way. (Link to play: http://justdoodiecp.weebly.com/play-thin-ice.html)
This game has preset boards. The game I am making will have random board generation. I have run into many issues with this.
I am currently coding in Mathematica, but would appreciate any input.
So far, I have been creating a "random walk" in a square grid. The grid is a two dimensional list of {},{0},{1},{2},{3}. The walk moves either up, down, left or right, never diagonally and never staying in the same place. It also cannot walk back on itself.The walk replaces {} with {0} at the positions it goes to and cannot go to any spot with 0,1,2, or 3 currently in place. It starts at 2. The goal is to get it to eventually stop at 3, but I'm thinking I may do away with the value of three until the walk is complete. It can travel adjacent to another section of the path, with no wall in between them. This walk continues on until it traps itself OR the amount of {0} is equal to the dimensions minus the amount of obstacles that should be placed. The amount of obstacles is inputted when calling the function. However, I do not want the function to trap itself but instead fill up the board with {0} until the amount of {0} is equal to the dimensions minus the amount of obstacles that should be placed. Once the path is generated, all obstacles will be placed in any blank spots, replacing them with {1}.
Here is my code so far:
gameboard2[dim_, obs_] :=
(*0 = blank, 1= obstacles, 2 = start, 3 = exit, 4 = water*)
Module[{i, j, board = {}, boardPts = {}, x = 1, y = 1, endx = 1,
endy = 1, prevx = 1, prevy = 1, possibleValues = {}, pt = {},
blankspc = dim^2 - 2 - obs},
board = Table[{}, {i, 1, dim + 2}, {j, 1, dim + 2}];
(*Generation of border*)
Table[board[[1, i]] = {1}, {i, 1, dim + 2}];
Table[board[[dim + 2, i]] = {1}, {i, 1, dim + 2}];
For[i = 1, i <= Length[board], i++,
board[[i, 1]] = {1};
board[[i, dim + 2]] = {1};
];
(*Random start point placement*)
While[Count[board, {2}, 2] != 1,
x = RandomChoice[Table[i, {i, 1, dim + 2}]];
y = RandomChoice[Table[i, {i, 1, dim + 2}]];
If[board[[x, y]] != {1}, board[[x, y]] = {2}];
];
(*Random exit point placement*)
While[Count[board, {3}, 2] != 1,
endx = RandomChoice[Table[i, {i, 1, dim + 2}]];
endy = RandomChoice[Table[i, {i, 1, dim + 2}]];
If[board[[endx, endy]] != {1}, board[[endx, endy]] = {3}];
];
(*Random path generation*)
(*x needs to be between 2 and dim+1 and y needs to be between 2 and dim+1*)
For[i = 1, i <= blankspc, i++,
prevx = x; prevy = y;
possibleValues = {};
(*Testing position of x and y, making sure they are not on the side or the corner of the board*)
If[x == 2,
If[y == 2, (*bottom left*) possibleValues = {{x, y + 1}, {x + 1, y}},
If[y == dim + 1, (*top left*)
possibleValues = {{x, y - 1}, {x + 1, y}},
(*left side*) possibleValues = {{x, y + 1}, {x, y - 1}, {x + 1, y}}]],
If[x == dim + 1,
If[y == 2, (*bottom right*) possibleValues = {{x, y + 1}, {x - 1, y}},
If[y == dim + 1, (*top right*)
possibleValues = {{x, y - 1}, {x - 1, y}},
(*right side*)
possibleValues = {{x, y + 1}, {x, y - 1}, {x - 1, y}}]],
If[y == 2, (*bottom*)
possibleValues = {{x, y - 1}, {x - 1, y}, {x + 1, y}},
If[y == dim + 1,(*top*)
possibleValues = {{x, y + 1}, {x - 1, y}, {x + 1,
y}},(*Not on any side or corner*)
If[x > 2 && x < dim + 1 && y > 2 && y < dim + 1,
possibleValues = {{x, y + 1}, {x, y - 1}, {x + 1, y}, {x - 1,
y}}, possibleValues = {{x, y}}]
]
]
]
];
(*Ensure every position in possibleValues is equal to {} on the board*)
For[j = 1, j <= Length[possibleValues], j++,
If[board[[possibleValues[[j, 1]], possibleValues[[j, 2]]]] != {},
possibleValues[[j]] = {}];
];
possibleValues =
Delete[possibleValues, Position[possibleValues, {}]];
(*Random choosing of a point to move to*)
pt = RandomChoice[possibleValues];
x = pt[[1]];
y = pt[[2]];
If[board[[x, y]] == {}, board[[x, y]] = {0}];
];
(*Prints amount of {} and the length of the path to see if it became the right length*)
Print[blankspc];
Print[Count[board, {0}, 2]];
Return[TableForm[board]]
]
Output:
In[30]:= gameboard2[10, 30]
(*Note how many errors there are. This occurs when the path gets trapped and cannot move to any squares around it*)
During evaluation of In[30]:= RandomChoice::lrwl: The items for choice {} should be a list or a rule weights -> choices. >>
During evaluation of In[30]:= Part::partw: Part 2 of RandomChoice[{}] does not exist. >>
During evaluation of In[30]:= Part::pkspec1: The expression RandomChoice[{}][[2]] cannot be used as a part specification. >>
During evaluation of In[30]:= RandomChoice::argt: RandomChoice called with 0 arguments; 1 or 2 arguments are expected. >>
During evaluation of In[30]:= Part::partw: Part 1 of RandomChoice[] does not exist. >>
During evaluation of In[30]:= Part::partw: Part 2 of RandomChoice[] does not exist. >>
During evaluation of In[30]:= General::stop: Further output of Part::partw will be suppressed during this calculation. >>
During evaluation of In[30]:= Part::pkspec1: The expression RandomChoice[][[1]] cannot be used as a part specification. >>
During evaluation of In[30]:= RandomChoice::argt: RandomChoice called with 0 arguments; 1 or 2 arguments are expected. >>
During evaluation of In[30]:= Part::pkspec1: The expression RandomChoice[][[1]] cannot be used as a part specification. >>
During evaluation of In[30]:= General::stop: Further output of Part::pkspec1 will be suppressed during this calculation. >>
During evaluation of In[30]:= RandomChoice::argt: RandomChoice called with 0 arguments; 1 or 2 arguments are expected. >>
During evaluation of In[30]:= General::stop: Further output of RandomChoice::argt will be suppressed during this calculation. >>
During evaluation of In[30]:= 68
(*This is how many {0} there should be*)
During evaluation of In[30]:= 45
(*This is how many there are*)
{{{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}},
{{1}, {}, {}, {}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {1}},
{{1}, {}, {}, {}, {0}, {0}, {0}, {0}, {}, {}, {0}, {1}},
{{1}, {}, {}, {}, {0}, {0}, {0}, {0}, {}, {}, {0}, {1}},
{{1}, {}, {}, {}, {0}, {0}, {0}, {0}, {}, {}, {0}, {1}},
{{1}, {}, {}, {}, {0}, {0}, {0}, {0}, {}, {}, {0}, {1}},
{{1}, {}, {}, {}, {0}, {0}, {}, {}, {}, {}, {0}, {1}},
{{1}, {}, {}, {}, {}, {3}, {}, {0}, {0}, {}, {0}, {1}},
{{1}, {}, {}, {}, {}, {0}, {0}, {0}, {0}, {0}, {0}, {1}},
{{1}, {}, {}, {}, {}, {0}, {}, {2}, {0}, {}, {}, {1}},
{{1}, {}, {}, {}, {}, {0}, {0}, {0}, {0}, {}, {}, {1}},
{{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}}}]
I've looked all over the internet for various path generation tips and tricks, but none have been what I am looking for. Most allow the path to go back on itself, or move diagonally, or generate a maze. These will not work.
Can anyone help me uncover the correct logic? If I was not clear, please ask questions! :)
Thanks!
Related
Working with implicit functions in Mathematica returned from other functions
I have a equation inv = (x + f) (y + g) == z; But for some reason I cannot CountourPlot it, even though copy-pasting output, for example {(2 + x) (2 + y)} == {11} into CountourPlot works. I've tried both Hold and Defer to no luck. What's happening and how I can fix this problem? Actual code: inv00 = (x + 1) (y + 1) == z inv01 = inv00 /. {z -> 2} ContourPlot[inv01, {x, 0, 1}, {y, 0, 1}] ContourPlot[(1 + x) (1 + y) == 2, {x, 0, 1}, {y, 0, 1}]
how can I change value of array in a loop in mathematica?
I wrote a code in matlab as below: T= ((1-(-1)) * rand([4,4],'double') + (-1) * ones(4,4)); for i=1:4 for j=1:i T(j,i)=TT(i,j); end T(i,i)=0; end Now, I want to write this code in mathematica as below: T = RandomReal[{-1, 1}, {4, 4}]; For[i = 1, i < 5, i++, For[ j = 1, j < i, j++, T[[j, i]] = T[[i, j]]] T[[i, i]] = 0]; But it doesn't work! Could you tell me about my mistakes? Thank you.
SeedRandom[1234]; t = u = RandomReal[{-1, 1}, {4, 4}]; t // MatrixForm If must use For For[i = 1, i < 5, i++, For[j = 1, j < i, j++, t[[j, i]] = t[[i, j]]]; t[[i, i]] = 0]; It mutates t t // MatrixForm One way to do this functionally (l = LowerTriangularize[u, -1]) + Transpose[l]
Can i return list in Mathematica function?
In my code I'm trying to return list of numbers from my function but it gives me just null. sifra[zprava_, klic_] := Module[ {c, n, e, m, i, z, pocCyklu, slovo}, pocCyklu = Ceiling[Divide[StringLength[zprava], 5]]; c = Array[{}, pocCyklu]; z = Partition[Characters[zprava], 5, 5, 1, {}]; For[i = 1, i < pocCyklu + 1, i++, slovo = StringJoin # z[[i]]; m = StringToInteger[slovo]; n = klic[[1]]; e = klic[[2]]; c[[i]] = PowerMod[m, e, n]; ] Return[c] ]; sif = sifra[m, verejny] After the cycles are done there should be 2 numbers in c. Print[c] works OK it prints list with 2 elements in it but sif is null. Return[c] gives me: Null Return[{28589400926821874625642026431141504822, 2219822858062194181357669868096}]
You could write the function like this: sifra[zprava_, klic_] := Module[{c, n, e, m, i, z, pocCyklu, slovo}, pocCyklu = Ceiling[Divide[StringLength[zprava], 5]]; c = ConstantArray[{}, pocCyklu]; z = Partition[Characters[zprava], 5, 5, 1, {}]; For[i = 1, i < pocCyklu + 1, i++, slovo = StringJoin#z[[i]]; m = ToExpression[slovo]; {n, e} = klic; c[[i]] = PowerMod[m, e, n]]; c] Demonstrating use with example data: sifra["9385637605763057836503784603456", {124, 2}] {20, 97, 41, 9, 4, 113, 36} You could also write the function like this: sifra[zprava_, {n_, e_}] := Module[{z}, z = Partition[Characters[zprava], 5, 5, 1, {}]; Map[PowerMod[ToExpression[StringJoin[#]], e, n] &, z]]
filling 2dArrays with another 2DArray in Lua
is there a way to fill a 2d Array with another 2dArray in Lua? what im using right now is this local T4 = { {0, 0, 0, 0, 0}, {0, 0, 1, 0, 0}, {0, 1, 1, 1, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }; function myFunc() local Pieces = {} for x = 1, 5 do Pieces[x]={} for y = 1, 5 do Pieces[y][x] = T4[y][x]--the error is probably here end end end but this is not working,ive got a good reason to do this and its because this process gets repeated a lot of times so using T4 is not an option also im not getting an error,the program just stops there,so any idea how to do this?
You've got your indexes messed up: function myFunc() local Pieces = {} for y = 1, 5 do Pieces[y]={} for x = 1, 5 do Pieces[y][x] = T4[y][x] end end return Pieces end You could copy any table using something like this: function copytable(t) local copy = {} for key,val in pairs(t) do if type(val) == 'table' then copy[key] = copytable(val) else copy[key] = val end end return copy end This is off the top of my head so use with cation. It definitely doesn't deal with cyclic references (a table which contains a reference to the same table).
How to draw three-dimensional image: Plot3D NDSolve
m = 10; c = 2; k = 5; F = 12; NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t], x[0] == 0, x'[0] == 0}, x[t], {t, 0, 30}] {f, 0, 5} ( 0=< f <= 5 ) How to draw three-dimensional image: x = u(t,f) ............ If f = 0.1,0.2,... 5, We can solve the equation: NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t], x[0] == 0, x'[0] == 0}, x[t], {t, 0, 30}] x is a function of t and f ............... m = 10; c = 2; k = 5; F = 12; f = 0.1 s = NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t], x[0] == 0, x'[0] == 0}, x[t], {t, 0, 30}] Plot[Evaluate[x[t] /. s], {t, 0, 30}, PlotRange -> All] f = 0.1 f = 0.2 f = 0.3 f = 5 How to draw three-dimensional image: x = u(t,f)
Here goes a solution. m = 10; c = 2; k = 5; F = 12; NumberOfDiscrit$f = 20;(* Number of points you want to divide 0<=f<=5*) NumberOfDiscrit$t = 100;(* Number of points you want to divide 0<=t<=30 *) fValues = Range[0., 5., 5./(NumberOfDiscrit$f - 1)]; tValues = Range[0., 30., 30./(NumberOfDiscrit$t - 1)]; res = Map[(x /. First#First# NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*#*t])*x[t] == F*Sin[2*Pi*#*t], x[0] == 0, x'[0] == 0}, x, {t, 0, 30}]) &, fValues]; AllDat = Map[(##tValues) &, res]; InterpolationDat = Flatten[Table[ Transpose#{tValues, Table[fValues[[j]], {i, 1, NumberOfDiscrit$t}], AllDat[[j]]}, {j, 1, NumberOfDiscrit$f}], 1]; Final3DFunction = Interpolation[InterpolationDat]; Plot3D[Final3DFunction[t, f], {t, 0, 30}, {f, 0, 5}, PlotRange -> All, PlotPoints -> 60, MaxRecursion -> 3, Mesh -> None] You can use Manipulate to dynamically change some of the parameters. By the way the above 3D picture may be misleading if one takes f as a continuous variable in u(t,f). You should note that the numerical solution seems to blow up for asymptotic values of t>>30. See the picture below. Hope this helps you out.
You could also do something like this Clear[f] m = 10; c = 2; k = 5; F = 12; s = NDSolve[{m*Derivative[2, 0][x][t, f] + c*Derivative[1, 0][x][t, f] + (k*Sin[2*Pi*f*t])*x[t, f] == F*Sin[2*Pi*f*t], x[0, f] == 0, Derivative[1, 0][x][0, f] == 0}, x, {t, 0, 30}, {f, 0, .2}] Plot3D[Evaluate[x[t, f] /. s[[1]]], {t, 0, 30}, {f, 0, .2}, PlotRange -> All]
This should do it. m = 10; c = 2; k = 5; F = 12; fun[f_?NumericQ] := Module[ {x, t}, First[x /. NDSolve[ {m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t], x[0] == 0, x'[0] == 0}, x, {t, 0, 30} ] ] ] ContourPlot[fun[f][t], {f, 0, 5}, {t, 0, 30}] Important points: The pattern _?NumericQ prevents fun from being evaluated for symbolc arguments (think fun[a]), and causing NDSolve::nlnum errors. Since NDSolve doesn't appear to localize its function variable (t), we needed to do this manually using Module to prevent conflict between the t used in NDSolve and the one used in ContourPlot. (You could use a differently named variable in ContourPlot, but I think it was important to point out this caveat.) For a significant speedup in plotting, you can use memoization, as pointed out by Mr. Wizard. Clear[funMemo] (* very important!! *) funMemo[f_?NumericQ] := funMemo[f] = Module[{x, t}, First[x /. NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t], x[0] == 0, x'[0] == 0}, x, {t, 0, 30}]]] ContourPlot[funMemo[f][t], {f, 0, 5}, {t, 0, 30}] (* much faster than with fun *) If you're feeling adventurous, and willing to explore Mathematica a bit more deeply, you can further improve this by limiting the amount of memory the cached definitions are allowed to use, as I described here. Let's define a helper function for enabling memoization: SetAttributes[memo, HoldAll] SetAttributes[memoStore, HoldFirst] SetAttributes[memoVals, HoldFirst] memoVals[_] = {}; memoStore[f_, x_] := With[{vals = memoVals[f]}, If[Length[vals] > 100, f /: memoStore[f, First[vals]] =.; memoVals[f] ^= Append[Rest[memoVals[f]], x], memoVals[f] ^= Append[memoVals[f], x]]; f /: memoStore[f, x] = f[x]] memo[f_Symbol][x_?NumericQ] := memoStore[f, x] Then using the original, non-memoized fun function, plot as ContourPlot[memo[fun][f][t], {f, 0, 5}, {t, 0, 30}]