아이작의 매력은 매판 맵과 아이템이 바뀌는 로그라이크 형식이라고 생각한다.
아이작의 맵은 시드를 기반으로 로직에 따라서 생성된다. 원래는 아이템을 작성 해야하는 차례이지만
시드를 기반으로 아이템도 바뀌다보니 자연스레 시드와 관련된 맵을 먼저 작성하게 되었다.
백준 문제와 제작자의 인터뷰를 통해 수월하게 진행할 수 있었다
제작자 인터뷰
아이작 관련 백준 문제
맵 생성의 기본 골조는 다음과 같다
1. 랜덤으로 시드가 정해진다
2. 시드를 기반으로 각 스탭마다 유사 난수 생성기를 통해서 방을 생성한다
-> 이떄 유사 난수 생성기는 선형 합동 생성기를 사용한다
3. 시드가 같다면 같은 맵이 생성 된다
-> 맵 생성 알고리즘이 잘 짜여져 있다면 동일안 시드는 동일한 횟수로 유사 난수 생성기를 호출한다.
시드를 랜덤으로 정하는 것 자체는 어려울 것 없다.
시드의 길이와 사용될 문자열을 정한 뒤
일반 적으로 사용되는 Random 관련 함수를 사용한다.
GameManager.cs
private string GenerateSeed() { string temp = ""; for (int i = 0; i < 9; i++) { int tempInt = UnityEngine.Random.Range(0, SeedString.Length); if (i == 4) temp += "-"; else temp += SeedString[tempInt]; } return temp; }
1 )유사 난수 생성기
GameManager.cs
public void Rand() { // Sn+1 = (A x Sn + C ) Mod M Sn = (A * Sn + C) % M; Rand_Cnt++; }
이를 사용하는 코드
public int RandInt(int left, int right)
{
Rand();
return (int)((Sn % (right - left + 1)) + left);
}
// P보다 작을 경우 true;
public bool Chance(int p)
{
return (RandInt(1, 100) <= p);
}
public T Choice<T>(List<T> rooms)
{
int cnt = rooms.Count();
int temp = RandInt(0, cnt - 1);
return rooms[temp];
}
2) 방 생성
MapManager.cs
//방들이 최대한 사이클을 생성하지 않도록 public bool CanCreateRoom(int x, int y) { if (x < 0 || x >= s_mapMaxX) return false; if (y < 0 || y >= s_mapMaxY) return false; // 이미 방이 있다면 넘어간다. if (s_roomGraph[x, y] == 1) return false; // 인접한 방이 2개 이상이면 방을 생성하지 않는다. if (CheckAdjacenctRoomCnt(x, y) >= 2) return false; // 위조건을 만족해도 50보다 작아야 방을 생성 if (!Managers.Game.Chance(50)) return false; return true; }
//1.BFS를 통한 방 생성 while (roomCnt < Managers.Game.N) { roomClassQueue.Enqueue(Managers.Game.Choice(Rooms)); while (roomClassQueue.Count != 0) { RoomClass front = roomClassQueue.Dequeue(); //Right, Down, Left, Up int[] dx = { 0, 1, 0, -1 }; int[] dy = { 1, 0, -1, 0 }; for (int i = 0; i < 4; i++) { if (roomCnt == Managers.Game.N) break; int nx = front.XPos + dx[i]; int ny = front.YPos + dy[i]; if (CanCreateRoom(nx, ny)) { rc = new RoomClass(nx, ny); front._adjacencentRooms[i] = rc; rc._adjacencentRooms[(i + 2) % 4] = front; s_roomGraph[nx, ny] = 1; Rooms.Add(rc); roomCnt++; roomClassQueue.Enqueue(rc); XMin = Math.Min(XMin, nx); YMin = Math.Min(YMin, ny); XMax = Math.Max(XMax, nx); YMax = Math.Max(YMax, ny); } } } }
선형 합동 생성기는 실행 횟수에 따라서 값이 달라진다. 즉 같은 횟수에서는 같은 값이 나온다.
알고리즘이 정확한 순서를 따르고, 외부요소의 영향이 없다면 같은 모양의 방이 생성될 것이다.