Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions patch.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
--- src/GameUtils/Procedural/Diamond.cs
+++ src/GameUtils/Procedural/Diamond.cs
@@ -1,4 +1,5 @@
-using GameUtils.Types.Collections;
+using System.Numerics;
+using GameUtils.Types.Collections;

namespace GameUtils.Procedural;

@@ -45,11 +46,11 @@
var mx = x + halfStep;
var my = y + halfStep;

- map[mx, my] = valueFactory(AverageInt(map, x, y, x + step, y, x, y + step, x + step, y + step), range);
- map[mx, y] = valueFactory(AverageInt(map, x, y, x + step, y, mx, my, mx, y - step), range);
- map[x, my] = valueFactory(AverageInt(map, x, y, x, y + step, mx, my, x - step, my), range);
- map[x + step, my] = valueFactory(AverageInt(map, x + step, y, x + step, y + step, mx, my, x + step + step, my), range);
- map[mx, y + step] = valueFactory(AverageInt(map, x, y + step, x + step, y + step, mx, my, mx, y + step + step), range);
+ map[mx, my] = valueFactory(AverageInt(map, new(x, y), new(x + step, y), new(x, y + step), new(x + step, y + step)), range);
+ map[mx, y] = valueFactory(AverageInt(map, new(x, y), new(x + step, y), new(mx, my), new(mx, y - step)), range);
+ map[x, my] = valueFactory(AverageInt(map, new(x, y), new(x, y + step), new(mx, my), new(x - step, my)), range);
+ map[x + step, my] = valueFactory(AverageInt(map, new(x + step, y), new(x + step, y + step), new(mx, my), new(x + step + step, my)), range);
+ map[mx, y + step] = valueFactory(AverageInt(map, new(x, y + step), new(x + step, y + step), new(mx, my), new(mx, y + step + step)), range);
}
}

@@ -60,13 +61,13 @@
return map;
}

- private static float AverageInt(Grid<int> map, int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy)
+ private static float AverageInt(Grid<int> map, Vector2 a, Vector2 b, Vector2 c, Vector2 d)
{
var sum = 0f;
var count = 0;
- if (ax >= 0 && ax < map.Width && ay >= 0 && ay < map.Height) { sum += map[ax, ay]; count++; }
- if (bx >= 0 && bx < map.Width && by >= 0 && by < map.Height) { sum += map[bx, by]; count++; }
- if (cx >= 0 && cx < map.Width && cy >= 0 && cy < map.Height) { sum += map[cx, cy]; count++; }
- if (dx >= 0 && dx < map.Width && dy >= 0 && dy < map.Height) { sum += map[dx, dy]; count++; }
+ if (map.IsInBounds(a)) { sum += map[a]; count++; }
+ if (map.IsInBounds(b)) { sum += map[b]; count++; }
+ if (map.IsInBounds(c)) { sum += map[c]; count++; }
+ if (map.IsInBounds(d)) { sum += map[d]; count++; }
return count == 0 ? 0f : sum / count;
}
20 changes: 10 additions & 10 deletions src/GameUtils/Procedural/Diamond.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ public static Grid<int> Create(int size, int min, int max, float range, Func<flo
var mx = x + halfStep;
var my = y + halfStep;

map[mx, my] = valueFactory(AverageInt(map, x, y, x + step, y, x, y + step, x + step, y + step), range);
map[mx, y] = valueFactory(AverageInt(map, x, y, x + step, y, mx, my, mx, y - step), range);
map[x, my] = valueFactory(AverageInt(map, x, y, x, y + step, mx, my, x - step, my), range);
map[x + step, my] = valueFactory(AverageInt(map, x + step, y, x + step, y + step, mx, my, x + step + step, my), range);
map[mx, y + step] = valueFactory(AverageInt(map, x, y + step, x + step, y + step, mx, my, mx, y + step + step), range);
map[mx, my] = valueFactory(AverageInt(map, (x, y), (x + step, y), (x, y + step), (x + step, y + step)), range);
map[mx, y] = valueFactory(AverageInt(map, (x, y), (x + step, y), (mx, my), (mx, y - step)), range);
map[x, my] = valueFactory(AverageInt(map, (x, y), (x, y + step), (mx, my), (x - step, my)), range);
map[x + step, my] = valueFactory(AverageInt(map, (x + step, y), (x + step, y + step), (mx, my), (x + step + step, my)), range);
map[mx, y + step] = valueFactory(AverageInt(map, (x, y + step), (x + step, y + step), (mx, my), (mx, y + step + step)), range);
}
}

Expand All @@ -60,14 +60,14 @@ public static Grid<int> Create(int size, int min, int max, float range, Func<flo
return map;
}

private static float AverageInt(Grid<int> map, int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy)
private static float AverageInt(Grid<int> map, (int x, int y) a, (int x, int y) b, (int x, int y) c, (int x, int y) d)
{
var sum = 0f;
var count = 0;
if (ax >= 0 && ax < map.Width && ay >= 0 && ay < map.Height) { sum += map[ax, ay]; count++; }
if (bx >= 0 && bx < map.Width && by >= 0 && by < map.Height) { sum += map[bx, by]; count++; }
if (cx >= 0 && cx < map.Width && cy >= 0 && cy < map.Height) { sum += map[cx, cy]; count++; }
if (dx >= 0 && dx < map.Width && dy >= 0 && dy < map.Height) { sum += map[dx, dy]; count++; }
if (map.IsInBounds(a.x, a.y)) { sum += map[a.x, a.y]; count++; }
if (map.IsInBounds(b.x, b.y)) { sum += map[b.x, b.y]; count++; }
if (map.IsInBounds(c.x, c.y)) { sum += map[c.x, c.y]; count++; }
if (map.IsInBounds(d.x, d.y)) { sum += map[d.x, d.y]; count++; }
return count == 0 ? 0f : sum / count;
}
}
73 changes: 73 additions & 0 deletions src/GameUtils/Procedural/Diamond.cs.orig
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using GameUtils.Types.Collections;

namespace GameUtils.Procedural;

/// <summary>
/// Generates a diamond-square map
/// </summary>
public static class Diamond
{
/// <summary>
/// Creates a new diamond-square map from the specified parameters.
/// </summary>
/// <param name="size">Height and width. Must be a power-of-two plus one (e.g. 129, 257, 513).</param>
/// <param name="min">Min value of the initial seed</param>
/// <param name="max">Max value of the initial seed</param>
/// <param name="range">The initial range for the next step</param>
/// <param name="nextRange">A method that will be passed the current range and is expected to return the range for the next iteration</param>
/// <param name="valueFactory">A method that will be passed an average value and a range, and is expected to return an integer map value</param>
/// <param name="seed">Optional random seed for reproducible generation. Uses a thread-safe shared instance when null.</param>
/// <exception cref="ArgumentException">Thrown when <paramref name="size"/> is not a power-of-two plus one.</exception>
public static Grid<int> Create(int size, int min, int max, float range, Func<float, float> nextRange, Func<float, float, int> valueFactory, int? seed = null)
{
var n = size - 1;
if (n < 1 || (n & (n - 1)) != 0)
{
throw new ArgumentException("Size must be a power-of-two plus one (e.g. 3, 5, 9, 17, 33, ...).", nameof(size));
}

var r = seed.HasValue ? new Random(seed.Value) : Random.Shared;
var map = new Grid<int>(size, size);
map[0, 0] = r.Next(min, max);
map[0, size - 1] = r.Next(min, max);
map[size - 1, 0] = r.Next(min, max);
map[size - 1, size - 1] = r.Next(min, max);

var step = size - 1;

while (step > 1)
{
var halfStep = step / 2;
for (var y = 0; y < size - 1; y += step)
{
for (var x = 0; x < size - 1; x += step)
{
var mx = x + halfStep;
var my = y + halfStep;

map[mx, my] = valueFactory(AverageInt(map, x, y, x + step, y, x, y + step, x + step, y + step), range);
map[mx, y] = valueFactory(AverageInt(map, x, y, x + step, y, mx, my, mx, y - step), range);
map[x, my] = valueFactory(AverageInt(map, x, y, x, y + step, mx, my, x - step, my), range);
map[x + step, my] = valueFactory(AverageInt(map, x + step, y, x + step, y + step, mx, my, x + step + step, my), range);
map[mx, y + step] = valueFactory(AverageInt(map, x, y + step, x + step, y + step, mx, my, mx, y + step + step), range);
}
}

range = nextRange(range);
step = halfStep;
}

return map;
}

private static float AverageInt(Grid<int> map, int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy)
{
var sum = 0f;
var count = 0;
if (ax >= 0 && ax < map.Width && ay >= 0 && ay < map.Height) { sum += map[ax, ay]; count++; }
if (bx >= 0 && bx < map.Width && by >= 0 && by < map.Height) { sum += map[bx, by]; count++; }
if (cx >= 0 && cx < map.Width && cy >= 0 && cy < map.Height) { sum += map[cx, cy]; count++; }
if (dx >= 0 && dx < map.Width && dy >= 0 && dy < map.Height) { sum += map[dx, dy]; count++; }
return count == 0 ? 0f : sum / count;
}
}
Loading