Das ist die offizielle Rust-Bibliothek für die Programmierung von Spielern für die Software-Challenge Germany auf crates.io.
- Vollständige Kommunikation mit Spielservern
- Vollständige Berechnung von Spielzügen
- Simulation von Spielzügen auf GameStates (Beispielsweise für den Minimax Algorithmus vorausgesetzt)
- Simulation vom letzten Zug statt Auslesen des gesamten neuen GameStates für bessere Performance
- Viele Funktionen, welche die Entwicklung erleichtern
- Kapselung auf alle größeren Datentypen
- Der Rust Compiler inlined solche Funktionen. Dadurch hat man direkten Zugriff auf die Variablen (das ist schneller).
Eröffnet bei Fehlern oder euer Meinung nach fehlenden Funktionen gerne ein Issue auf GitHub und/oder schreibt es in den Software-Challenge Discord im "Probleme" Kanal. Außerdem könnt ihr euch an
- SturmEnte
- NichtNil5
auf Discord wenden.
In examples können Beispiel-Implementierungen für Spieler gefunden werden.
- Installiert Rust (mindestens Version 1.85 für 2024 edition) und Cargo (wird mit Rust installiert).
- Erzeugt über die Kommandozeile mit
cargo new best_playerein neues Cargo-Projekt. - Setzt eine beliebige Rust Entwicklungsumgebung auf und importiert das Projekt.
- Kopiert anschließend den Zufallsspieler (siehe
examples/basic_player) oder folgende Spielervorlage inmain.rs:
use socha::prelude::*;
struct Player {
game_state: Option<GameState>,
}
impl Client for Player {
fn on_move_request(&mut self) -> Option<Move> {
println!("Received a move request!");
get_possible_moves(&self.game_state.as_mut().unwrap()).first().cloned()
}
fn on_game_over(&mut self) {
println!("Game over!");
}
fn on_game_state_updated(&mut self, game_state: GameState ) {
game_state.get_board().print_board();
self.game_state = Some(game_state);
println!("Game state updated!");
}
}
fn main() {
let client = Player { game_state: None };
start_client_from_commandline_args(client).unwrap();
}- Führt
cargo add sochaaus, um die Bibliothek zu eurem Projekt hinzuzufügen. - Startet euren Spieler mit
cargo runund verbindet ihn mit dem Spielserver (siehe den Ein-neues-Spiel-erstellen Guide mit einem "Manuell gestarteten Computerspieler")
Die folgenden Befehle könnne beim starten des Spielers mit angehangen werden.
Diese Befehle sind vorallem für das Contest-System relevant, weil es damit dem Spieler die benötigten Informationen übergibt.
| Befehl | Beschreibung | Standart |
|---|---|---|
| -h, --host | Der Host, zu dem eine Verbindung hergestellt werden soll. | 'localhost' |
| -p, --port | Der Port des Hosts. | 13050 |
| -r, --reservation | Reservierungscode für ein vorbereitetes Spiel. | / |
Es stehen euch verschiedene Methoden und Datenstrukturen zur Verfügung. Hier werden die wichtigsten einmal erklärt.
Grundsätzlich sollte in der Regel nur alles im socha::game für euch relevant sein.
socha::client
Der Client ist für den Gameflow und das Übermitteln von Spielereignissen an euer Programm zuständig. Mit dem Client-trait müsst ihr ein eigenes Struct mit den entsprechenden Funktionen erstellen. Euren Client könnt ihr dann an eine der Startfunktionen übermitteln. Wie euer Client aussehen kann, könnt ihr hier sehen.
socha::game::board::Board
Das Board ist das Spielfeld. Es wird im Gamestate verwendet, um das aktuelle Spielfeld zu speichern. Es stehen hier außerdem einige Methoden zu Verfügung.
Hiermit kann das Board in die Konsole ausgegeben werden.
Hiermit kann eine Zelle mit den gegebenen Koordinaten vom Board ausgelesen werden.
Hiermit kann eine Zelle auf die angegebene Farbe gesetzt werden.
Wenn die Zelle auf dem Spielfeld ist und somit die Zelle auf die Farbe gesetzt wurde, wird true zurückgegeben, ansonsten wird false zurückgegeben.
Hiermit kann ein Spielstein auf dem Spielfeld platziert werden.
Der Spielstein wird nur platziert, wenn alle Koordinaten des Spielsteins noch nicht belegt und innerhalb vom Spielfeld sind.
Wenn der Spielstein erfolgreich platziert wurde, gibt die Funktion true zurück, ansonsten false.
Diese Überprüfung verbraucht etwas mehr Leistung als die unchecked Variante; wenn ihr euch sicher seid, dass der Spielstein dort platziert werden darf, nutzt die unchecked Variante.
Diese Funktion tut das gleiche wie die place_piece Funktion, nur dass keine Überprüfung stattfindet, ob der Spielstein platziert werden kann.
socha::game::color::Color
Color ist ein Enum mit allen 4 Farben aus dem Spiel.
Es wird beispielsweise im GameState genutzt, um Anzugeben welche Farbe einen Zug tätigen soll.
Außerdem wird Color im Board verwendet, um die Spielfelder mit der belegten Farbe zu markieren.
Mit dieser Funktion kann ein String in Großbuchstaben in das Color Enum umgewandelt werden.
Wichtig: Wenn der String nicht "BLUE", "YELLOW", "RED", "GREEN" übereinstimmt, schlägt die Methode fehl.
socha::game::constants
In Constants können Konstanten vom Spiel gefunden werden.
Für Blokus sind BOARD_SIZE und BOARD_SIZE_I vorhanden. Beide sind 20, der Unterschied ist, dass BOARD_SIZE usize und BOARD_SIZE_I isize.
socha::game::coordinate
Coordinate enthält zum einen das Struct Coordinate, welches überall wo mit Koordinaten gearbeitet wird verwendet wird.
Außerdem enthält es einige Funktionen, mit denen ein Vektor von Coordinate transformiert werden kann.
- x: isize
- y: isize
Das Struct Coordinate enthält die Funktionen add, subtract, multiply, divide mit denen Koordinaten berechnet werden können.
Außerdem die Funktionen rotate und flip_on_vertical mit denen die Koordinate rotiert und gespiegelt werden können.
Normalisiert die gegebenen Koordinaten, das heißt sie werden so verschoben, dass die Koordinate links-oben im Ursprung (0,0) ist.
Rotiert die Koordinaten nach der angegebenen Rotation. Die Koordinaten werden danach nicht normalisiert, die Koordinate links-oben liegt danach also wahrscheinlich nicht im Ursprung.
Spiegelt die gegebenen Koordinaten auf der y-Achse. Die Koordinaten werden danach nicht normalisiert, die oberste-linke Koordinate liegt danach also wahrscheinlich nicht im Ursprung.
socha::game::gamerulelogic
Dieses Modul enthält Funktionen zum Berechnen und Überprüfen von Spielzügen.
Die Funktionen geben keine Aussetz-Züge zurück, außer bei der direkten Prüfung eines Move mit skip = true.
Gibt alle möglichen Spielzüge für das aktuelle Team im angegebenen GameState zurück.
In der ersten Runde werden die möglichen Startzüge berechnet, in allen folgenden Runden die möglichen normalen Platzierungszüge.
Aussetz-Züge sind nicht enthalten.
Gibt alle möglichen Startzüge für das aktuelle Team zurück. Dabei wird der Start-Spielstein in allen unterschiedlichen Rotationen und Spiegelungen an den Spielfeldrändern geprüft.
Gibt alle möglichen normalen Platzierungszüge für das aktuelle Team zurück. Dafür werden alle noch verfügbaren Spielsteine und alle gültigen Eckfelder berücksichtigt.
get_possible_moves_for_piece(gamestate: &GameState, piece: &PieceType, valid_fields: &[Coordinate]) -> Vec<Move>
Gibt alle möglichen Platzierungszüge für den angegebenen Spielsteintyp zurück.
Die übergebenen valid_fields werden als mögliche Eckfelder verwendet.
Diese Funktion ist nur für Spielzüge nach der ersten Runde vorgesehen.
Gibt alle freien Spielfelder zurück, die diagonal an einen Spielstein der angegebenen Farbe angrenzen. Felder außerhalb des Spielfelds, belegte Felder und Felder mit direktem Kantenkontakt zu einem eigenen Spielstein werden ausgeschlossen.
Gibt alle Koordinaten zurück, die auf dem Board mit der angegebenen Farbe belegt sind.
Prüft, ob ein Spielzug im angegebenen GameState gültig ist.
Ein Aussetz-Zug ist direkt gültig.
Bei einem Platzierungszug wird geprüft, ob der Spielstein noch verfügbar ist, alle Koordinaten innerhalb des Spielfelds liegen und keine belegten Felder verwendet werden.
Außerdem darf der neue Spielstein keinen direkten Kantenkontakt zu einem eigenen Spielstein haben.
Sobald das Team bereits einen Spielstein auf dem Board besitzt, muss mindestens ein Eckkontakt zu einem eigenen Spielstein vorhanden sein.
socha::game::gamestate::GameState
Der GameState enthält alle Informationen zu einem Spielstand.
starting_piece: PieceType- Der Startspielstein für dieses Spielis_starting_team_one: bool- Gibt an, ob Team 1 (Blau/Rot) oder Team 2 (Gelb/Grün) startetboard: Board- Das aktuelle Spielfeldturn: u8- Die aktuelle Zugnummerround: u8- Die aktuelle Rundennummercurrent_turn_color: Color- Die Farbe des Spielers, der am Zug istpieces: [Vec<PieceType>; 4]- Die verfügbaren Spielsteine für jede Farbe (Blau, Gelb, Rot, Grün)
new(starting_piece, is_starting_team_one, board, turn, round, current_turn_color, blue_pieces, yellow_pieces, red_pieces, green_pieces) -> GameState
Erstellt einen neuen GameState mit den angegebenen Werten.
Wendet einen Spielzug auf den GameState an und validiert ihn vorher.
Gibt true zurück, wenn der Zug gültig war und angewendet wurde, ansonsten false.
Wendet einen Spielzug auf den GameState an, ohne ihn zu validieren.
Dies ist schneller, aber kann zu inkonsistenten Spielständen führen, wenn ein ungültiger Zug angewendet wird.
Gibt die Farbe des Spielers zurück, der am Zug ist.
Setzt die Farbe des Spielers, der am Zug ist.
Gibt die aktuelle Zugnummer zurück.
Setzt die Zugnummer.
Gibt die aktuelle Rundennummer zurück.
Setzt die Rundennummer.
Gibt den Startspielstein zurück.
Setzt den Startspielstein.
Gibt zurück, ob Team 1 startet.
Setzt, ob Team 1 startet.
Gibt eine Referenz auf das Spielfeld zurück.
Setzt das Spielfeld.
Gibt die verfügbaren Spielsteine für die angegebene Farbe zurück.
Setzt die verfügbaren Spielsteine für die angegebene Farbe.
socha::game::move::Move
Ein Move beschreibt einen Spielzug.
Die enthaltenen Felder sind öffentlich und können direkt ausgelesen werden.
Gibt die Farbe des Spielers an, der den Zug ausführt.
Gibt den Typ des Spielsteins an, der platziert werden soll.
Gibt die X-Koordinate der Position des Spielsteins an.
Gibt die Y-Koordinate der Position des Spielsteins an.
Gibt an, ob der Spielstein gespiegelt werden soll.
Gibt die Rotation des Spielsteins an.
Gibt an, ob der Spieler in diesem Zug aussetzt.
new(color: Color, piece: PieceType, x: usize, y: usize, is_flipped: bool, rotation: Rotation, skip: bool) -> Move
Erstellt einen neuen Spielzug mit den angegebenen Werten.
socha::game::piece::Piece
Ein Piece beschreibt einen Spielstein mit einem PieceType, einer Rotation und der Information, ob er gespiegelt ist.
Erstellt einen neuen Spielstein mit dem angegebenen Typ, der Rotation und der Spiegelung.
Gibt die Koordinaten des Spielsteins nach Rotation und Spiegelung zurück.
Die Koordinaten werden anschließend normalisiert, sodass sie bei (0, 0) beginnen und nur positive Werte enthalten.
Gibt eine Referenz auf den Typ des Spielsteins zurück.
Setzt den Typ des Spielsteins.
Gibt eine Referenz auf die Rotation des Spielsteins zurück.
Setzt die Rotation des Spielsteins.
Gibt eine Referenz darauf zurück, ob der Spielstein gespiegelt ist.
Setzt, ob der Spielstein gespiegelt werden soll.
socha::game::piece::PieceType
PieceType beschreibt die Form eines Spielsteins.
Es stehen folgende Typen zur Verfügung:
Mono, Domino, TrioL, TrioI, TetroO, TetroT, TetroI, TetroL, TetroZ, PentoL, PentoT, PentoV, PentoS, PentoZ, PentoI, PentoP, PentoW, PentoU, PentoR, PentoX und PentoY.
Gibt alle möglichen Varianten des Spielsteintyps zurück.
Jeder Eintrag enthält die Koordinaten sowie die zugehörige Rotation und Spiegelung.
Wenn filter auf true gesetzt wird, werden geometrisch identische Varianten nur einmal zurückgegeben.
Gibt die unveränderten Basis-Koordinaten des Spielsteintyps zurück.
Diese Koordinaten enthalten noch keine Rotation oder Spiegelung, beginnen bei (0, 0) und wachsen nur in positive Richtung.
Mit to_string kann ein Spielsteintyp in seinen Namen in Großbuchstaben umgewandelt werden, zum Beispiel "MONO" oder "PENTO_X".
Ein Spielsteintyp kann über das FromStr-Trait aus einem String geparst werden, zum Beispiel mit "PENTO_X".parse::\<PieceType\>().
Unterstützt werden die Namen aus der Liste der Varianten in Großbuchstaben.
Wenn der String keinem gültigen Spielsteintyp entspricht, wird ein ParsePieceTypeError zurückgegeben.
socha::game::rotation::Rotation
Rotation ist ein Enum mit dem die Rotation eines Spielsteins angegeben wird.
Es stehen die vier Varianten None, Right, Mirror und Left zur Verfügung.
Mit dieser Funktion kann ein String in Großbuchstaben in das Rotation-Enum umgewandelt werden.
Die gültigen Strings sind "NONE", "RIGHT", "MIRROR" und "LEFT".
Wenn der String keinem dieser Werte entspricht, wird ein Fehler zurückgegeben.
Mit dieser Funktion kann eine Zahl in das Rotation-Enum umgewandelt werden.
Die Zuordnung ist 0 zu None, 1 zu Right, 2 zu Mirror und 3 zu Left.
Wenn die Zahl keinem dieser Werte entspricht, wird ein Fehler zurückgegeben.
Mit to_string kann eine Rotation wieder in einen String umgewandelt werden.
Das Ergebnis ist immer der jeweilige String in Großbuchstaben: "NONE", "RIGHT", "MIRROR" oder "LEFT".
- game/*
- connection/parser/*
Für die Teilnahme an der Software-Challenge dürfen alle Dateien aus diesem Repository beliebig verwendet und verändert werden.
Bis zur crates.io Version 0.2.2 wurde die Bibliothek von Simon Creates zur Verfügung gestellt.