Wave function collapse: Difference between revisions

Content added Content deleted
m (→‎{{header|C}}: grammar)
(Created Nim solution.)
Line 283: Line 283:
│ # # # # │ # # # # # # │ # # # # # │
│ # # # # │ # # # # # # │ # # # # # │
└──────────────────────────────────┴──────────────────────────────────┴──────────────────────────────────┘</syntaxhighlight>
└──────────────────────────────────┴──────────────────────────────────┴──────────────────────────────────┘</syntaxhighlight>

=={{header|Nim}}==
{{trans|C}}
<syntaxhighlight lang="Nim">import std/[algorithm, math, random]

template XY(row, col, width: int): int =
col + row * width

template XYZ(page, row, col, height, width: int): int =
XY(XY(page, row, height), col, width)

const Blocks = @[byte 0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
1, 1, 1,
0, 1, 0,
0, 1, 0,
0, 1, 1,
0, 1, 0,
0, 1, 0,
1, 1, 1,
0, 0, 0,
0, 1, 0,
1, 1, 0,
0, 1, 0]


proc wfc(blocks: seq[byte]; bdim: (int, int, int); tdim: (int, int); ): seq[byte] =
let (td0, td1) = tdim
let n = td0 * td1
var adj = newSeq[int](n * 4) # Indices in R of the four adjacent blocks.

for i in 0..<td0:
for j in 0..<td1:
adj[XYZ(i, j, 0, td1, 4)]= XY(floorMod(i-1, td0), floorMod(j, td1), td1)
adj[XYZ(i, j, 1, td1, 4)]= XY(floorMod(i, td0), floorMod(j-1, td1), td1)
adj[XYZ(i, j, 2, td1, 4)]= XY(floorMod(i, td0), floorMod(j+1, td1), td1)
adj[XYZ(i, j, 3, td1, 4)]= XY(floorMod(i+1, td0), floorMod(j, td1), td1)

let (bd0, bd1, bd2) = bdim

var horz = newSeq[byte](bd0 * bd0)
for i in 0..<bd0:
for j in 0..<bd0:
horz[XY(i, j, bd0)]= 1
for k in 0..<bd1:
if blocks[XYZ(i, k, 0, bd1, bd2)] != blocks[XYZ(j, k, bd2-1, bd1, bd2)]:
horz[XY(i, j, bd0)]= 0

var vert = newSeq[byte](bd0 * bd0)
for i in 0..<bd0:
for j in 0..<bd0:
vert[XY(i, j, bd0)]= 1
for k in 0..<bd2:
if blocks[XYZ(i, 0, k, bd1, bd2)] != blocks[XYZ(j, bd1-1, k, bd1, bd2)]:
vert[XY(i, j, bd0)]= 0
break

var allow = newSeq[byte](4 * (bd0 + 1) * bd0)
allow.fill(1)
for i in 0..<bd0:
for j in 0..<bd0:
allow[XYZ(0, i, j, bd0+1, bd0)] = vert[XY(j, i, bd0)]
allow[XYZ(1, i, j, bd0+1, bd0)] = horz[XY(j, i, bd0)]
allow[XYZ(2, i, j, bd0+1, bd0)] = horz[XY(i, j, bd0)]
allow[XYZ(3, i, j, bd0+1, bd0)] = vert[XY(i, j, bd0)]

var
todo = newSeq[int](n)
wave = newSeq[byte](n * bd0)
entropy = newSeq[int](n)
indices = newSeq[int](n)
possible = newSeq[int](bd0)
var r = newSeq[int](n)
r.fill(bd0)
while true:
var c = 0
for i in 0..<n:
if bd0 == r[i]:
todo[c]= i
inc c
if c == 0: break
var min = bd0
for i in 0..<c:
entropy[i] = 0
for j in 0..<bd0:
let val = allow[XYZ(0, r[adj[XY(todo[i],0,4)]], j, bd0+1, bd0)] and
allow[XYZ(1, r[adj[XY(todo[i],1,4)]], j, bd0+1, bd0)] and
allow[XYZ(2, r[adj[XY(todo[i],2,4)]], j, bd0+1, bd0)] and
allow[XYZ(3, r[adj[XY(todo[i],3,4)]], j, bd0+1, bd0)]
wave[XY(i, j, bd0)] = val
entropy[i] += val.int
if entropy[i] < min: min = entropy[i]
if min == 0:
r.setLen(0)
break
var d = 0
for i in 0..<c:
if min == entropy[i]:
indices[d] = i
inc d
var ndx = indices[rand(d - 1)]
let ind = ndx * bd0
d = 0
for i in 0..<bd0:
if wave[ind + i] != 0:
possible[d] = i
inc d
r[todo[ndx]] = possible[rand(d - 1)];

if r.len == 0: return @[]
result = newSeq[byte]((1 + td0 * (bd1 - 1)) * (1 + td1 * (bd2 - 1)))
for i0 in 0..<td0:
for i1 in 0..<bd1:
for j0 in 0..<td1:
for j1 in 0..<bd2:
result[XY(XY(j0, j1, bd2-1), XY(i0, i1, bd1-1), 1+td1*(bd2-1))] =
blocks[XYZ(r[XY(i0, j0, td1)], i1, j1, bd1, bd2)]

const BDims = (5, 3, 3)
const Size = (8, 8)
randomize()
let tile = wfc(Blocks, BDims, Size)
if tile.len == 0: quit QuitSuccess
for i in 0..16:
for j in 0..16:
stdout.write " #"[tile[XY(i, j, 17)]], ' '
echo()
</syntaxhighlight>

{{out}}
<pre> # # # #
# # # # # # # # # # # #
# # # #
# # # # # # # # # # # # # # # #
# # # # # #
# # # # # # # # # # # # #
# # # # # # # #
# # # # # # # # # # # # # #
# # # # # #
# # # # # # # # # # # # # # #
# # # # # #
# # # # # # # # # # # # # # #
# # # # # #
# # # # # # # # #
# # # # # #
# # # # # # # # # # # # # # # #
# # # # </pre>


=={{header|Perl}}==
=={{header|Perl}}==