昔のゲームの迷路生成部分が謎だという動画から記事を探し、 Unity のコードと wiki のリンクが載っていたので両方見ながら java (paiza.io) で試してみました。
https://qiita.com/ELIXIR/items/3ada72c77a43f786977e
https://https://en.wikipedia.org/wiki/Entombed_(Atari_2600)
import java.util.*;
//ATARI 'Entombed' Maze Generate TEST
//https://qiita.com/ELIXIR/items/3ada72c77a43f786977e
//https://en.wikipedia.org/wiki/Entombed_(Atari_2600)
public class Main {
public static void main(String[] args) throws Exception {
byte[] map = new byte[] {
0,0,0,0,0,0,0,0,0,0, //データの座標が1つズレていること
1,0,0,0,0,0,0,0,0,0
};
print(map);
for(int j=0; j<20; j++) {
update(map);
print(map);
}
}
private static final byte[] mysteryTable = { // X=0:open,1:wall,2:random
1,1,1,2,0,0,2,2, 1,1,1,1,2,0,0,0,
1,1,1,2,0,0,0,0, 2,0,1,2,2,0,0,0
};
private static final byte[] posTbl = new byte[] { 10,11,0,1,2 }; //a,b,c,d,e
private static void update(byte[] map) {
map[0] = wallOrOpen();
map[9] = wallOrOpen();
for(int x=0; x<8; x++) {
int idx = 0;
for(int i : posTbl) idx = (idx << 1) | map[x+i];
byte v = mysteryTable[idx];
if(v == 2) v = wallOrOpen();
map[x+12] = v;
}
for(int i=0; i<8; i++) map[i+1] = map[i+12];
}
private static final Random random = new Random();
private static byte wallOrOpen() {
return (byte)random.nextInt(2);
}
private static final char WALL = '壁';
private static final char OPEN = ' ';
private static char[] buf = new char[] {
WALL, WALL,
OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN,
OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN,
WALL, WALL
};
private static void print(byte[] map) {
for(int i=0; i<8; i++) buf[i+2] = buf[17-i] = map[i+1]==0?OPEN:WALL;
System.out.println(new String(buf));
}
}
壁壁 壁壁
壁壁壁壁 壁壁壁 壁壁 壁壁壁 壁壁壁壁
壁壁 壁 壁壁 壁 壁壁
壁壁 壁壁壁 壁壁壁壁壁壁 壁壁壁 壁壁
壁壁壁壁 壁壁壁壁
壁壁 壁壁 壁壁壁壁 壁壁 壁壁
壁壁壁壁 壁 壁 壁 壁 壁壁壁壁
壁壁 壁 壁 壁壁 壁壁 壁 壁 壁壁
壁壁壁壁 壁 壁 壁 壁 壁壁壁壁
壁壁 壁 壁壁 壁壁 壁 壁壁
壁壁 壁壁壁 壁 壁 壁壁壁 壁壁
壁壁 壁 壁壁壁壁壁壁 壁 壁壁
壁壁 壁 壁壁壁 壁壁壁 壁 壁壁
壁壁壁壁 壁壁 壁壁壁壁
壁壁 壁 壁壁壁 壁壁 壁壁壁 壁 壁壁
壁壁 壁 壁 壁 壁 壁壁
壁壁 壁 壁 壁壁 壁壁 壁 壁 壁壁
壁壁 壁 壁 壁 壁 壁壁
壁壁 壁 壁壁 壁壁壁壁 壁壁 壁 壁壁
壁壁壁壁 壁 壁壁 壁 壁壁壁壁
壁壁壁 壁壁壁 壁壁壁 壁壁壁
それっぽいような気もしますが、何度も作ってみると結構な確率で行き止まりになるような気も…。
壁壊しアイテムがあるようなので、数個は常に持ってるような前提なんでしょうかね。
ATARI 2600 は CPU 6502 みたいで流石にどんな特徴があったのか分かりません。けれど java よりは c で書いたほうがもっとそれっぽかった(?)かも知れません。(一応配列を byte にしてみたりはしましたが。)
6502 をチラと見てみて、ゼロページとインデックスレジスタの使い方に技とかありそうです。
https://ja.wikipedia.org/wiki/MOS_6502
レジスタが少ない(というか無い)のでメモリを節約する為にレジスタでビット演算しようにもデータは定数かメモリからにしかならないのかな? …懐かしい感覚。 (Z80 だった身としては実感は無いですが。)
c にしてみた。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
char wallOrOpen() {
return (char)(rand() & 1);
}
char map[] = {
0,0,0,0,0,0,0,0,0,0, //データの座標が1つズレていること
1,0,0,0,0,0,0,0,0,0
};
char mysteryTable[] = { // X=0:open,1:wall,2:random
1,1,1,2,0,0,2,2, 1,1,1,1,2,0,0,0,
1,1,1,2,0,0,0,0, 2,0,1,2,2,0,0,0
};
char posTbl[] = { 10,11,0,1,2 }; //a,b,c,d,e
void update() {
map[0] = wallOrOpen();
map[9] = wallOrOpen();
for(int x=0; x<8; x++) {
int idx = 0;
for(int i=0; i<sizeof(posTbl); i++) idx = (idx << 1) | map[x+posTbl[i]];
char v = mysteryTable[idx];
if(v == 2) v = wallOrOpen();
map[x+12] = v;
}
for(int i=0; i<8; i++) map[i+1] = map[i+12];
}
#define WALL 'X'
#define OPEN ' '
char buf[] = "XX XX";
void print() {
for(int i=0; i<8; i++) buf[i+2] = buf[17-i] = map[i+1]?WALL:OPEN;
printf("%s\n", buf);
}
int main(void) {
srand((unsigned int)(clock() & UINT_MAX));
print();
for(int i=0; i<20; i++) {
update();
print();
}
}
XX XX
XX XXXX XXXX XXXX XX
XX X X X X XX
XX XX XX XX XX XX XX
XXXX X XX X XXXX
XX XXX X X XXX XX
XX XX XX XX
XXXX XXX XXX XXXX
XX X XX X XX
XXXXX XX XX XXXXX
XX X X XX X X XX
XX XX X XXXX X XX XX
XXXX X X X X XXXX
XXX XX X X XX XXX
XXX XX X X XX XXX
XXX X XX XX X XXX
XX X XX XX X XX
XX XX XX XX XX
XXXX XX XX XX XXXX
XX XX XX XX XX
XX XXX XXXX XXX XX
ワザと泥臭い感じを狙いましたが、まぁ、大して変わりません。