<commit_before>package tintor.sokoban;

import java.math.BigInteger;
import java.util.Arrays;

import tintor.common.Array;
import tintor.common.AutoTimer;
import tintor.common.BipartiteMatching;
import tintor.common.Bits;
import tintor.common.PairVisitor;
import tintor.common.Util;
import tintor.common.Visitor;
import tintor.sokoban.Level.MoreThan256CellsError;

interface CellToChar {
	char fn(Cell cell);
}

enum Dir {
	Left, Up, Right, Down
}

final class Move {
	final Cell cell;
	final Dir dir;
	final int dist;

	Move(Cell cell, Dir dir, int dist) {
		assert cell != null;
		assert dir != null;
		assert dist > 0;
		this.cell = cell;
		this.dir = dir;
		this.dist = dist;
	}
}

final class Cell {
	final Cell[] dir = new Cell[4];
	Move[] moves;
	final int xy;
	final boolean goal;
	int goal_ordinal = -1;
	boolean box;
	char ch; // used only for loading
	int id;
	boolean alive;
	boolean tunnel;
	boolean bottleneck;
	int room = -1;

	static final int Infinity = Integer.MAX_VALUE / 2; // limitation due to Hungarian
	int[] distance_box; // distance[goal_orginal]

	boolean bottleneck_tunnel() {
		return bottleneck && tunnel;
	}

	Cell dir(Dir d) {
		return dir[d.ordinal()];
	}

	Cell rdir(Dir d) {
		return dir[Level.reverseDir(d.ordinal())];
	}

	Cell(int xy, char ch) {
		this.xy = xy;
		this.goal = ch == LowLevel.Goal || ch == LowLevel.AgentGoal || ch == LowLevel.BoxGoal;
		if (ch == LowLevel.AgentGoal)
			ch = LowLevel.Agent;
		if (ch == LowLevel.BoxGoal)
			ch = LowLevel.Box;
		if (ch == LowLevel.Goal)
			ch = LowLevel.Space;
		this.ch = ch;
		box = ch == LowLevel.Box;
	}
}

final class CellLevel {
	final String name;
	final char[] buffer;
	final Cell[] cells;
	final int alive;
	final int num_boxes;
	final Visitor visitor;
	final State start;
	final int[] goal;
	final CellLevelTransforms transforms;
	final boolean has_goal_rooms;
	final boolean has_goal_zone;

	CellLevel(char[] buffer, String name) {
		int w = 0;
		while (buffer[w] != '\n')
			w++;
		assert buffer.length % (w + 1) == 0;
		this.name = name;
		this.buffer = buffer;

		// Create cells
		Cell[] grid = new Cell[buffer.length];
		for (int xy = 0; xy < buffer.length; xy++)
			if (buffer[xy] != LowLevel.Wall && buffer[xy] != '\n')
				grid[xy] = new Cell(xy, buffer[xy]);<commit_msg>Added CellLevel.loadAll<commit_after>package tintor.sokoban;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;

import tintor.common.Array;
import tintor.common.AutoTimer;
import tintor.common.BipartiteMatching;
import tintor.common.Bits;
import tintor.common.PairVisitor;
import tintor.common.Util;
import tintor.common.Visitor;
import tintor.sokoban.Level.MoreThan256CellsError;

interface CellToChar {
	char fn(Cell cell);
}

enum Dir {
	Left, Up, Right, Down
}

final class Move {
	final Cell cell;
	final Dir dir;
	final int dist;

	Move(Cell cell, Dir dir, int dist) {
		assert cell != null;
		assert dir != null;
		assert dist > 0;
		this.cell = cell;
		this.dir = dir;
		this.dist = dist;
	}
}

final class Cell {
	final Cell[] dir = new Cell[4];
	Move[] moves;
	final int xy;
	final boolean goal;
	int goal_ordinal = -1;
	boolean box;
	char ch; // used only for loading
	int id;
	boolean alive;
	boolean tunnel;
	boolean bottleneck;
	int room = -1;

	static final int Infinity = Integer.MAX_VALUE / 2; // limitation due to Hungarian
	int[] distance_box; // distance[goal_orginal]

	boolean bottleneck_tunnel() {
		return bottleneck && tunnel;
	}

	Cell dir(Dir d) {
		return dir[d.ordinal()];
	}

	Cell rdir(Dir d) {
		return dir[Level.reverseDir(d.ordinal())];
	}

	Cell(int xy, char ch) {
		this.xy = xy;
		this.goal = ch == LowLevel.Goal || ch == LowLevel.AgentGoal || ch == LowLevel.BoxGoal;
		if (ch == LowLevel.AgentGoal)
			ch = LowLevel.Agent;
		if (ch == LowLevel.BoxGoal)
			ch = LowLevel.Box;
		if (ch == LowLevel.Goal)
			ch = LowLevel.Space;
		this.ch = ch;
		box = ch == LowLevel.Box;
	}
}

final class CellLevel {
	final String name;
	final char[] buffer;
	final Cell[] cells;
	final int alive;
	final int num_boxes;
	final Visitor visitor;
	final State start;
	final int[] goal;
	final CellLevelTransforms transforms;
	final boolean has_goal_rooms;
	final boolean has_goal_zone;

	public static ArrayList<CellLevel> loadAll(String filename) {
		int count = LevelLoader.numberOfLevels(filename);
		ArrayList<CellLevel> levels = new ArrayList<CellLevel>();
		for (int i = 1; i <= count; i++)
			try {
				String name = filename + ":" + i;
				levels.add(new CellLevel(LevelLoader.load(name), name));
			} catch (MoreThan256CellsError e) {
			}
		return levels;
	}

	CellLevel(char[] buffer, String name) {
		int w = 0;
		while (buffer[w] != '\n')
			w++;
		assert buffer.length % (w + 1) == 0;
		this.name = name;
		this.buffer = buffer;

		// Create cells
		Cell[] grid = new Cell[buffer.length];
		for (int xy = 0; xy < buffer.length; xy++)
			if (buffer[xy] != LowLevel.Wall && buffer[xy] != '\n')
				grid[xy] = new Cell(xy, buffer[xy]);
{'fraction_non_alphanumeric': 0.12990146792680474, 'fraction_numerical': 0.005630404182585964, 'mean_word_length': 3.657303370786517, 'pattern_counts': {'":': 1, '<': 9, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2211449', 'n_tokens_mistral': 1943, 'n_tokens_neox': 1795, 'n_words': 520}