<commit_before>package asmcup.sandbox;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;

import javax.imageio.ImageIO;

import asmcup.runtime.*;
import asmcup.runtime.Robot;

public class Sandbox {
	protected Mouse mouse;
	protected Menu menu;
	protected Canvas canvas;
	protected Frame frame;
	protected CodeEditor codeEditor;
	protected Debugger debugger;
	
	protected Image backBuffer;
	protected World world;
	protected Robot robot;
	protected int panX, panY;
	protected Image[] ground, wall, obstacles, hazards, coins;
	protected Image bot;
	
	public Sandbox() throws IOException {
		mouse = new Mouse(this);
		menu = new Menu(this);
		canvas = new Canvas(this);
		frame = new Frame(this);
		codeEditor = new CodeEditor(this);
		world = new World();
		debugger = new Debugger(this);
		
		canvas.addMouseListener(mouse);
		canvas.addMouseMotionListener(mouse);
		
		ground = loadImage("/ground.png");
		wall = loadImage("/wall.png");
		obstacles = loadImage("/obstacles.png");
		hazards = loadImage("/hazards.png");
		bot = ImageIO.read(getClass().getResource("/robot.png"));
		coins = loadImage("/gold.png");
	}
	
	public int getPanX() {
		return panX;
	}
	
	public int getPanY() {
		return panY;
	}
	
	public Mouse getMouse() {
		return mouse;
	}
	
	public Menu getMenu() {
		return menu;
	}
	
	public Canvas getCanvas() {
		return canvas;
	}
	
	public Frame getFrame() {
		return frame;
	}
	
	public CodeEditor getCodeEditor() {
		return codeEditor;
	}
	
	public Debugger getDebugger() {
		return debugger;
	}
	
	public World getWorld() {
		return world;
	}
	
	public Robot getRobot() {
		return robot;
	}
	
	public void pan(int dx, int dy) {
		panX += dx;
		panY += dy;
	}
	
	public void teleport(float x, float y) {
		world.position(robot, x, y);
	}
	
	protected Image[] loadImage(String path) throws IOException {
		URL url = getClass().getResource(path);
		Image sheet = ImageIO.read(url);
		Image[] variants = new Image[4];
		
		for (int i=0; i < 4; i++) {
			Image img = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB);
			Graphics g = img.getGraphics();
			g.drawImage(sheet, -i * 32, 0, null);
			variants[i] = img;
		}
		
		return variants;
	}
	
	public void run() {
		robot = new Robot(1);
		world.addRobot(robot);
		frame.setVisible(true);
		
		long lastTick = System.currentTimeMillis();
		
		while (frame.isVisible()) {
			lastTick = System.currentTimeMillis();
			
			synchronized (world) {
				world.tick();
				debugger.repaint();
			}
			
			if (backBuffer != null) {
				synchronized (backBuffer) {
					draw();
				}
			}
			<commit_msg>Fixed redrawing to be synchronized to world updates to avoid concurrent cell modication.<commit_after>package asmcup.sandbox;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;

import javax.imageio.ImageIO;

import asmcup.runtime.*;
import asmcup.runtime.Robot;

public class Sandbox {
	protected Mouse mouse;
	protected Menu menu;
	protected Canvas canvas;
	protected Frame frame;
	protected CodeEditor codeEditor;
	protected Debugger debugger;
	
	protected Image backBuffer;
	protected World world;
	protected Robot robot;
	protected int panX, panY;
	protected Image[] ground, wall, obstacles, hazards, coins;
	protected Image bot;
	
	public Sandbox() throws IOException {
		mouse = new Mouse(this);
		menu = new Menu(this);
		canvas = new Canvas(this);
		frame = new Frame(this);
		codeEditor = new CodeEditor(this);
		world = new World();
		debugger = new Debugger(this);
		
		canvas.addMouseListener(mouse);
		canvas.addMouseMotionListener(mouse);
		
		ground = loadImage("/ground.png");
		wall = loadImage("/wall.png");
		obstacles = loadImage("/obstacles.png");
		hazards = loadImage("/hazards.png");
		bot = ImageIO.read(getClass().getResource("/robot.png"));
		coins = loadImage("/gold.png");
	}
	
	public int getPanX() {
		return panX;
	}
	
	public int getPanY() {
		return panY;
	}
	
	public Mouse getMouse() {
		return mouse;
	}
	
	public Menu getMenu() {
		return menu;
	}
	
	public Canvas getCanvas() {
		return canvas;
	}
	
	public Frame getFrame() {
		return frame;
	}
	
	public CodeEditor getCodeEditor() {
		return codeEditor;
	}
	
	public Debugger getDebugger() {
		return debugger;
	}
	
	public World getWorld() {
		return world;
	}
	
	public Robot getRobot() {
		return robot;
	}
	
	public void pan(int dx, int dy) {
		panX += dx;
		panY += dy;
	}
	
	public void teleport(float x, float y) {
		world.position(robot, x, y);
	}
	
	protected Image[] loadImage(String path) throws IOException {
		URL url = getClass().getResource(path);
		Image sheet = ImageIO.read(url);
		Image[] variants = new Image[4];
		
		for (int i=0; i < 4; i++) {
			Image img = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB);
			Graphics g = img.getGraphics();
			g.drawImage(sheet, -i * 32, 0, null);
			variants[i] = img;
		}
		
		return variants;
	}
	
	public void run() {
		robot = new Robot(1);
		world.addRobot(robot);
		frame.setVisible(true);
		
		long lastTick = System.currentTimeMillis();
		
		while (frame.isVisible()) {
			lastTick = System.currentTimeMillis();
			
			synchronized (world) {
				world.tick();
				debugger.repaint();
				
				if (backBuffer != null) {
					synchronized (backBuffer) {
						draw();
					}
				}
			}
			
{'fraction_non_alphanumeric': 0.12483769245038026, 'fraction_numerical': 0.004080875533296235, 'mean_word_length': 3.554054054054054, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, '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': '4988429', 'n_tokens_mistral': 2065, 'n_tokens_neox': 1774, 'n_words': 482}