Session 11 (19.01.24) - RUB-INI-Theory-of-Machine-Learning/Info1_WS23-24 GitHub Wiki

In der elften Session starten wir mit der Programmierung eines Tetrisbots. Dazu müssen wir uns entscheiden wie solch eine Klasse in das Programm integriert wird. Danach muss der Bot lernen Spielzüge auszuführen. Schlussendlich bringen wir dem Bot bei eine zufällige Position gezielt anzusteuern.

Ziele

  • Botklasse in das Programm integrieren (mit Interface)
  • Spielzüge ausführen
  • Zufällige Position berechnen und dann gezielt ansteuern

Botklasse in das Programm integrieren (mit Interface)

class Bot {
	public:
	var current_time, speed;
	var optimal_position, current_tetromino, next_tetromino;
	var game;

	constructor(game, speed=100){
		this.game = game;
		this.speed = speed;
		this.current_time = time() + speed/2;
	}

	function step(){
		this.game.step();
	}

	function keyup(e){}
	function keydown(e){}

	function get_incoming_lines(){
		return this.game.get_incoming_lines();	
	}

	function add_incoming_lines(lines){
		this.game.add_incoming_lines(lines);
	}

	function get_outgoing_lines(){
		return this.game.get_outgoing_lines();	
	}

	function set_outgoing_lines(lines){
		this.game.set_outgoing_lines(lines);
	}
}
class Game {

    ...
    
    
	function get_incoming_lines(){
		return this.incoming_lines;	
	}

	function add_incoming_lines(lines){
		this.incoming_lines += lines;
	}

	function get_outgoing_lines(){
		return this.outgoing_lines;	
	}

	function set_outgoing_lines(lines){
		this.set_outgoing_lines = lines;
	}
}
setEventHandler("timer", function(event) {
    for var game_idx in 0:games.size() do {
        var game = games[game_idx];
        if game.get_outgoing_lines() > 0 then {
            games[(game_idx + 1) % games.size()].add_incoming_lines(game.outgoing_lines());
            game.set_outgoing_lines(0);
        }
        
        ...
    }
}

Zufällige Spielzüge ausführen

function step() {
    this.game.step();
    
    if time() - this.current_time > this.speed then {
        this.current_time = time();

        var key = this.game.bindings[Integer(math.random() * 4)];
        this.game.keydown(key);
    }
}

Zufällige Position gezielt ansteuern

function step(){
    this.game.step();
    
    if time() - this.current_time > this.speed then {
        this.current_time = time();
        
        if this.optimal_position == null or 
            (
                this.current_tetromino != this.game.tetromino.type or  
                this.next_tetromino != this.game.pool.next()
            )
        then {
            this.current_tetromino = this.game.tetromino.type;
            this.next_tetromino = this.game.pool.next();
            this.optimal_position = {
                "column": math.floor(math.random() * playfield.width + 1),
                "rotation": math.floor(math.random() * tetromino.max_rotations))
            };
        }
        
        if this.game.tetromino.rotation < this.optimal_position["rotation"] then this.game.keydown(this.game.bindings[0]);
        else if this.game.tetromino.rotation > this.optimal_position["rotation"] then this.game.keydown(this.game.bindings[1]);
        else if this.game.tetromino.column > this.optimal_position["column"] then this.game.keydown(this.game.bindings[2]);
        else if this.game.tetromino.column < this.optimal_position["column"] then this.game.keydown(this.game.bindings[3]);
    }
}