Related
The idea is simple, but the execution is bothering me.
I've created a small random dungeon generator that create a grid like this:
000001
000111
000111
001101
011101
011111
This is a sample 6x6 dungeon where 0 is a wall and 1 is an open path.
The conversion from this to some sort of tile id map is simple, and trivial, but creating the image itself is the hard part.
I want to know if there's a lib, or method to achieve that. If not, then what would you do?
This is not part of a game, and only a dungeon generator for DND. Any language is OK, but the generator was made in Go.
You can use OpenCV for this task. Probably PIL can do the same, don't have exp with it.
import cv2
import numpy as np
data_list = [
[0, 0, 0, 0, 0, 1],
[0, 0, 0, 1, 1, 1],
[0, 0, 0, 1, 1, 1],
[0, 0, 1, 1, 0, 1],
[0, 1, 1, 1, 0, 1],
[0, 1, 1, 1, 1, 1]
]
arr = np.array(data_list, dtype=np.uint8) * 255
arr = cv2.resize(arr, (0, 0), fx=50, fy=50, interpolation=cv2.INTER_NEAREST)
cv2.imshow("img", arr)
cv2.waitKey()
# or you can save on disk
cv2.imwrite("img.png", arr)
use np.block()
# a bunch of sprites/images, all the same size
# load them however you like
tiles = [...]
data_list = [
[0, 0, 0, 0, 0, 1],
[0, 0, 0, 1, 1, 1],
[0, 0, 0, 1, 1, 1],
[0, 0, 1, 1, 0, 1],
[0, 1, 1, 1, 0, 1],
[0, 1, 1, 1, 1, 1]
]
picture = np.block([
[tiles[k] for k in row]
for row in data_list
])
Or, if you use any kind of game engine, or something even more trivial, like SDL/PyGame, simply "blit" each tile.
PIL, as you found out, is perfectly capable of blitting one image (tile) onto another (whole map).
I kind of managed to get a solution, but it will be a Python only.
Using PIL I can make a mosaic with tile images and create the map. It's not a solid solution made from scratch but it can do the Job.
I'm still open for another approach.
My solution is this method here:
matrix = np.loadtxt(input_file, usecols=range(matrix_square), dtype=int)
tiles = []
for file in glob.glob("./tiles/*"):
im = Image.open(file)
tiles.append(im)
output = Image.new('RGB', (image_width,image_height))
for i in range(matrix_width):
for j in range(matrix_height):
x,y = i*tile_size,j*tile_size
index = matrix[j][i]
output.paste(tiles[index],(x,y))
output.save(output_file)
The matrix_square is the matrix dimensions (as a square). I'm still working on a better solution, but this is working fine for me.
You need to change the tile_size to match the tile resolution that you're using.
This is a generated dungeon with this method
The tiles are bad, but the grid is fine enough.
I was trying to get the nullity and kernel of a matrix over the complex field in Maxima.
I get strange results, though.
I can define a matrix A:
M : matrix([0, 1, 1, 0], [-1, 0, 0, 1], [0, 0, 0, 1], [0, 0, -1, 0]);
A : M + %i * ident(4);
... for reference, it looks like this:
%i 1 1 0
-1 %i 0 1
0 0 %i 1
0 0 -1 %i
If I then compute the nullity with nullity(A), I get 3.
If I compute the rank with rank(A), I also get 3.
And if I compute the nullspace with nullspace(A), I get:
span([-1, %i, 0, 0], [-%i, -1, 0, 0], [2%i, 2, 0, 0])
But this is pretty weird, because -%i * second(...) is [-1, %i, 0, 0], which is the first vector.
And indeed, when I do NullSpace[{{i, 1, 1, 0}, {-1, i, 0, 1}, {0, 0, i, 1}, {0, 0, -1, i}}] in Mathematica, I get that the nullspace has basis [%i, 1, 0, 0] and is 1-dimensional (not 3-dimensional).
What am I doing wrong?
You are doing everything right, as far as I can tell. The problem is a bug in Maxima, which I have reported: https://sourceforge.net/p/maxima/bugs/3158/
I don't see any simple way to work around it. I am working on fixing the bug.
Disclaimer, I'm a beginner.
I have an array that is 16 digits, limited to 0's and 1's. I'm trying to create a new array that contains only the index values for the 1's in the original array.
I currently have:
one_pos = []
image_flat.each do |x|
if x == 1
p = image_flat.index(x)
one_pos << p
image_flat.at(p).replace(0)
end
end
The image_flat array is [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
With the code above, one_pos returns [3, 3] rather than the [3, 5] that I'd expect.
Where am I going wrong?
Where am I going wrong?
When you call
image_flat.index(x)
It only returns first entry of x in image_flat array.
I guess there are some better solutions like this one:
image_flat.each_with_index do |v, i|
one_pos << i if v == 1
end
Try using each_with_index (http://apidock.com/ruby/Enumerable/each_with_index) on your array.
image_flat = [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
one_pos = []
image_flat.each_with_index do |value, index|
if value == 1
one_pos << index
end
end
I think this is the most elegant solution here:
image_flat.each_index.select{|i| image_flat[i] == 1}
Here is a solution if you are looking for a solution that doesn't reach out of the enumerable block although it does require a chained solution.
image_flat.each_with_index.select { |im,i| im==1 }.map { |arr| arr[1] }
Its chained and will require an additional lookup so Gena Shumilkin's answer will probably be more optimal for larger arrays.
This was what I originally thought Gena Shumilkin was trying to reach until I realized that solution used each_index instead of each_with_index.
Well, I'm very new to lua, LITERALLY today began to study this. So this is my code:
local l = {1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}
local n = table.getn(l)
local path = {{l[1], 1}}
local index = 1
for i=2,n do
if l[i] ~= l[i-1] then
index = index + 1
path[index][1] = l[i]
path[index][2] = 0
end
path[index][2] = path[index][2] + 1
end
What I want to do is to get path array (table) where zeros and ones should be grouped with their consequent amount. The output should be:
{{1, 1}, {0, 3}, {1, 3}, {0, 8}, {1, 1}}
But the problem is I get index expected, got nil error in line: path[index][1] = l[i] What is wrong with this code? index should be incremented and new item in path array should be created... But it isn't...
Index is set to to and you are attempting to index into path at position 2, which returns nil. Then you are attempting to set index 1 on nil. You need to create a table at index 2 of path. Try doing this
path[index] = {l[i], 0}
I am trying to work with matrixes; I have a model that has an attribute called "board", and its just a 4x4 matrix. I display this board in my view. So far so good. When I click a button, I send the param "board" with, for example, this structure:
{"utf8"=>"✓", "game_master"=>{"board"=>"Matrix[[0, 0, 0, 0], [0, 0, 1, 1], [0, 0, 1, 0], [1, 1, 0, 0]]"}, "commit"=>"Yolo"}
On the other side, in the controller, I try to recreate this board by creating a new gamemaster with board = Matrix[[0, 0, 0, 0], [0, 0, 1, 1], [0, 0, 1, 0], [1, 1, 0, 0]]. So far so good (NOT, I know that the param[:board] is just a string, that's my problem). Then, later on, when trying to iterate the matrix, I get this error:
undefined method `each_with_index' for "Matrix[[0, 0, 0, 0], [0, 0, 1, 1], [0, 0, 1, 0], [1, 1, 0, 0]]":String
Clearly, I bound :board to a string NOT a matrix. How would I go around converting that string into the corresponding matrix?
Thanks
UPDATE:
game_masters_controller.rb
def step
#game_master = GameMaster.new(game_master_params)
#game_master.step
respond_to do |format|
format.js
end
end
And:
private
def game_master_params
params.require(:game_master).permit(:board)
end
game_master.rb
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
if(self.board == nil)
self.board = get_new_board
end
end
Simply do:
arr = params[:game_master][:board].split(',').map(&:to_i).each_slice(4).to_a
# => [[0, 0, 0, 0], [0, 0, 1, 1], [0, 0, 1, 0], [0, 1, 0, 0]]
require 'matrix'
matrix = Matrix[*arr]
# => Matrix[[0, 0, 0, 0], [0, 0, 1, 1], [0, 0, 1, 0], [0, 1, 0, 0]]
Quick and dirty and not very secure:
class GameMaster
...
def board=(attr)
#board = eval attr
end
end
I would not run eval on something that gets submitted via a form. If the matrix is always 4x4, I would probably just submit the values in one long comma separated string like 0,0,0,1,1,1,0 .... Then I would use String#split to turn the large string into an array. Once you have one big array you could loop through it to generate an array of arrays that you can send to Matrix.new
string_params = 0,1,1,0,0,1
array_of_string = string_params.split(',')
array_of_arrays = array_of_string.each_slice(4).to_a
matrix = Matrix.new(array_of_arrays)
That should point you in the right direction.
Good luck!
Try this code:
(as the other answers mentioned, it's not secure to eval code coming from an input)
require 'matrix'
m = eval "Matrix[[0, 0, 0, 0], [0, 0, 1, 1], [0, 0, 1, 0], [1, 1, 0, 0]]"
=> Matrix[[0, 0, 0, 0], [0, 0, 1, 1], [0, 0, 1, 0], [1, 1, 0, 0]]
m.transpose
=> Matrix[[0, 0, 0, 1], [0, 0, 0, 1], [0, 1, 1, 0], [0, 1, 0, 0]]
Requiring the matrix.rb file will give you access to a lot of useful methods, check the documentation for further information.
http://ruby-doc.org/stdlib-2.1.0/libdoc/matrix/rdoc/Matrix.html