diff --git a/lib/data_objects/freyhoe_test.dart b/lib/data_objects/freyhoe_test.dart index dec8153..38f3d8e 100644 --- a/lib/data_objects/freyhoe_test.dart +++ b/lib/data_objects/freyhoe_test.dart @@ -3,6 +3,7 @@ import 'dart:developer' as developer; import 'dart:ffi'; import 'dart:math'; import 'package:logging/logging.dart' as logging; +import 'package:vector_math/vector_math_64.dart'; import 'dart:io'; import 'tetrio_multiplayer_replay.dart'; @@ -76,13 +77,64 @@ class HandlingHandler{ } } +class Board{ + int width; + int height; + int bufferHeight; + late List> board; + late int totalHeight; + + Board(this.width, this.height, this.bufferHeight){ + totalHeight = height+bufferHeight; + board = [for (var i = 0 ; i < totalHeight; i++) [for (var i = 0 ; i < width; i++) Tetromino.empty]]; + } + + @override + String toString() { + String result = ""; + for (var row in board){ + for (var cell in row) result += cell.name[0]; + result += "\n"; + } + return result; + } + + bool isOccupied(Coords coords) + { + if (coords.x < 0 || coords.x >= width || + coords.y < 0 || coords.y >= totalHeight || + board[coords.y][coords.x] != Tetromino.empty) return true; + return false; + } + + bool positionIsValid(Tetromino type, Coords coords, int r){ + List shape = shapes[type.index][r]; + for (Coords mino in shape){ + if (isOccupied(coords+mino)) return false; + } + return true; + } + + void writeToBoard(Tetromino type, Coords coords, int rot) { + if (!positionIsValid(type, coords, rot)) return; + List shape = shapes[type.index][rot]; + for (Coords mino in shape){ + var finalCoords = coords+mino; + board[finalCoords.y][finalCoords.x] = type; + } + } +} + +class Simulation{ + +} + // That thing allows me to test my new staff i'm trying to implement void main() async { var replayJson = jsonDecode(File("/home/dan63047/Документы/replays/6550eecf2ffc5604e6224fc5.ttrm").readAsStringSync()); ReplayData replay = ReplayData.fromJson(replayJson); - List queue = List.from(tetrominoes); TetrioRNG rng = TetrioRNG(replay.stats[0][0].seed); - List bag = rng.shuffleList(tetrominoes); + List queue = rng.shuffleList(tetrominoes); List events = readEventList(replay.rawJson); DataFullOptions? settings; HandlingHandler? handling; @@ -90,100 +142,155 @@ void main() async { int currentFrame = 0; events.removeAt(0); // get rig of Event.start Event nextEvent = events.removeAt(0); - List> board = [for (var i = 0 ; i < 40; i++) [for (var i = 0 ; i < 10; i++) Tetromino.empty]]; - Tetromino current = bag.removeAt(0); + Board board = Board(10, 20, 20); Tetromino? hold; int rot = 0; - int x = 4; - int y = 21; + Coords coords = Coords(4, 21); double gravityBucket = 0.00000000000000; - x += spawnPositionFixes[current.index].x.toInt(); - y += spawnPositionFixes[current.index].y.toInt(); + developer.log("Seed is ${replay.stats[0][0].seed}, first bag is $queue"); + Tetromino current = queue.removeAt(0); + //developer.log("Second bag is ${rng.shuffleList(tetrominoes)}"); + + int sonicDrop(){ + int height = coords.y; + while (board.positionIsValid(current, Coords(coords.x, height), rot)){ + height -= 1; + } + height += 1; + return height; + } + + Tetromino getNewOne(){ + if (queue.length <= 1) queue.addAll(rng.shuffleList(tetrominoes)); + developer.log("Next queue is $queue"); + return queue.removeAt(0); + } + + coords += spawnPositionFixes[current.index]; for (currentFrame; currentFrame <= replay.roundLengths[0]; currentFrame++){ - gravityBucket += settings != null ? settings.g! : 0; + gravityBucket += settings != null ? (handling!.sdfActive ? settings.g! * settings.handling!.sdf : settings.g!) : 0; + + int movement = handling != null ? handling.process_movenent(1.0) : 0; + if (board.positionIsValid(current, Coords(coords.x+movement, coords.y), rot)) coords.x += movement; + + int gravityImpact = 0; if (gravityBucket >= 1.0){ - y -= gravityBucket.truncate(); + gravityImpact = gravityBucket.truncate(); gravityBucket -= gravityBucket.truncate(); } - x += handling != null ? handling.process_movenent(1.0) : 0; - print("$currentFrame: $x $y"); + if (board.positionIsValid(current, Coords(coords.x, coords.y-gravityImpact), rot)) coords.y -= gravityImpact; + print("$currentFrame: $current at $coords\n$board"); + if (currentFrame == nextEvent.frame){ - print("Processing $nextEvent"); - switch (nextEvent.type){ - case EventType.start: - developer.log("go"); - break; - case EventType.full: - settings = (nextEvent as EventFull).data.options; - handling = HandlingHandler(settings!.handling!.das.toDouble(), settings.handling!.arr.toDouble()); - break; - case EventType.keydown: - nextEvent as EventKeyPress; - activeKeypresses[nextEvent.data.key] = nextEvent; - switch (nextEvent.data.key){ - case KeyType.rotateCCW: - rot = (rot-1)%4; - break; - case KeyType.rotateCW: - rot = (rot+1)%4; - break; - case KeyType.rotate180: - rot = (rot+2)%4; - break; - case KeyType.moveLeft: - handling!.movement_key_pressed(true, false); - case KeyType.moveRight: - handling!.movement_key_pressed(false, true); - case KeyType.softDrop: - // TODO: Handle this case. - case KeyType.hardDrop: - // TODO: Handle this case. - case KeyType.hold: - // TODO: Handle this case. - case KeyType.chat: - // TODO: Handle this case. - case KeyType.exit: - // TODO: Handle this case. - case KeyType.retry: - // TODO: Handle this case. - default: - developer.log(nextEvent.data.key.name); + while (currentFrame == nextEvent.frame){ + //print("Processing $nextEvent"); + switch (nextEvent.type){ + case EventType.start: + developer.log("go"); + break; + case EventType.full: + settings = (nextEvent as EventFull).data.options; + handling = HandlingHandler(settings!.handling!.das.toDouble(), settings.handling!.arr.toDouble()); + break; + case EventType.keydown: + nextEvent as EventKeyPress; + activeKeypresses[nextEvent.data.key] = nextEvent; + switch (nextEvent.data.key){ + case KeyType.rotateCCW: + rot = (rot+1)%4; + break; + case KeyType.rotateCW: + rot = (rot-1)%4; + break; + case KeyType.rotate180: + rot = (rot+2)%4; + break; + case KeyType.moveLeft: + handling!.movement_key_pressed(true, false); + break; + case KeyType.moveRight: + handling!.movement_key_pressed(false, true); + break; + case KeyType.softDrop: + handling!.sdfActive = true; + break; + case KeyType.hardDrop: + coords.y = sonicDrop(); + board.writeToBoard(current, coords, rot); + current = getNewOne(); + coords = Coords(4, 21) + spawnPositionFixes[current.index]; + //handling!.movement_key_released(true, true); + case KeyType.hold: + switch (hold){ + case null: + hold = current; + current = getNewOne(); + break; + case _: + Tetromino temp; + temp = hold; + hold = current; + current = temp; + break; + } + coords = Coords(4, 21) + spawnPositionFixes[current.index]; + break; + case KeyType.chat: + // TODO: Handle this case. + case KeyType.exit: + // TODO: Handle this case. + case KeyType.retry: + // TODO: Handle this case. + default: + developer.log(nextEvent.data.key.name); + } + break; + case EventType.keyup: + nextEvent as EventKeyPress; + switch (nextEvent.data.key){ + case KeyType.moveLeft: + handling!.movement_key_released(true, false); + break; + case KeyType.moveRight: + handling!.movement_key_released(false, true); + break; + case KeyType.softDrop: + handling?.sdfActive = false; + break; + case KeyType.rotateCCW: + // TODO: Handle this case. + case KeyType.rotateCW: + // TODO: Handle this case. + case KeyType.rotate180: + // TODO: Handle this case. + case KeyType.hardDrop: + // TODO: Handle this case. + case KeyType.hold: + // TODO: Handle this case. + case KeyType.chat: + // TODO: Handle this case. + case KeyType.exit: + // TODO: Handle this case. + case KeyType.retry: + // TODO: Handle this case. + } + activeKeypresses.remove(nextEvent.data.key); + break; + case EventType.end: + currentFrame = replay.roundLengths[0]+1; + break; + default: + developer.log("Event wasn't processed: ${nextEvent}", level: 900); + } + try{ + nextEvent = events.removeAt(0); } - break; - case EventType.keyup: - nextEvent as EventKeyPress; - switch (nextEvent.data.key){ - case KeyType.moveLeft: - handling!.movement_key_released(true, false); - case KeyType.moveRight: - handling!.movement_key_released(false, true); - case KeyType.softDrop: - // TODO: Handle this case. - case KeyType.rotateCCW: - // TODO: Handle this case. - case KeyType.rotateCW: - // TODO: Handle this case. - case KeyType.rotate180: - // TODO: Handle this case. - case KeyType.hardDrop: - // TODO: Handle this case. - case KeyType.hold: - // TODO: Handle this case. - case KeyType.chat: - // TODO: Handle this case. - case KeyType.exit: - // TODO: Handle this case. - case KeyType.retry: - // TODO: Handle this case. + catch (e){ + developer.log(e.toString()); } - activeKeypresses.remove(nextEvent.data.key); - break; - default: - developer.log("Event wasn't processed: ${nextEvent}", level: 900); - } - nextEvent = events.removeAt(0); - developer.log("Next is: $nextEvent"); + } + //developer.log("Next is: $nextEvent"); } } exit(0); diff --git a/lib/data_objects/tetrio_multiplayer_replay.dart b/lib/data_objects/tetrio_multiplayer_replay.dart index 648727e..ef8dc34 100644 --- a/lib/data_objects/tetrio_multiplayer_replay.dart +++ b/lib/data_objects/tetrio_multiplayer_replay.dart @@ -1,8 +1,6 @@ import 'dart:math'; import 'dart:typed_data'; -import 'package:vector_math/vector_math_64.dart'; - import 'tetrio.dart'; // I want to implement those fancy TWC stats @@ -752,52 +750,72 @@ enum Tetromino{ empty } +class Coords{ + int x; + int y; + + Coords(this.x, this.y); + + @override + String toString() { + return "($x; $y)"; + } + + Coords operator+(Coords other){ + return Coords(x+other.x, y+other.y); + } + + Coords operator-(Coords other){ + return Coords(x-other.x, y-other.y); + } +} + List tetrominoes = [Tetromino.Z, Tetromino.L, Tetromino.O, Tetromino.S, Tetromino.I, Tetromino.J, Tetromino.T]; -List>> shapes = [ +List>> shapes = [ [ // Z - [Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), Vector2(2, 1)], - [Vector2(2, 0), Vector2(1, 1), Vector2(2, 1), Vector2(1, 2)], - [Vector2(0, 1), Vector2(1, 1), Vector2(1, 2), Vector2(2, 2)], - [Vector2(1, 0), Vector2(0, 1), Vector2(1, 1), Vector2(0, 2)] + [Coords(0, 0), Coords(1, 0), Coords(1, 1), Coords(2, 1)], + [Coords(2, 0), Coords(1, 1), Coords(2, 1), Coords(1, 2)], + [Coords(0, 1), Coords(1, 1), Coords(1, 2), Coords(2, 2)], + [Coords(1, 0), Coords(0, 1), Coords(1, 1), Coords(0, 2)] ], [ // L - [Vector2(2, 0), Vector2(0, 1), Vector2(1, 1), Vector2(2, 1)], - [Vector2(1, 0), Vector2(1, 1), Vector2(1, 2), Vector2(2, 2)], - [Vector2(0, 1), Vector2(1, 1), Vector2(2, 1), Vector2(0, 2)], - [Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), Vector2(1, 2)] + [Coords(2, 0), Coords(0, 1), Coords(1, 1), Coords(2, 1)], + [Coords(1, 0), Coords(1, 1), Coords(1, 2), Coords(2, 2)], + [Coords(0, 1), Coords(1, 1), Coords(2, 1), Coords(0, 2)], + [Coords(0, 0), Coords(1, 0), Coords(1, 1), Coords(1, 2)] ], [ // O - [Vector2(0, 0), Vector2(1, 0), Vector2(0, 1), Vector2(1, 1)], - [Vector2(0, 0), Vector2(1, 0), Vector2(0, 1), Vector2(1, 1)], - [Vector2(0, 0), Vector2(1, 0), Vector2(0, 1), Vector2(1, 1)], - [Vector2(0, 0), Vector2(1, 0), Vector2(0, 1), Vector2(1, 1)] + [Coords(0, 0), Coords(1, 0), Coords(0, 1), Coords(1, 1)], + [Coords(0, 0), Coords(1, 0), Coords(0, 1), Coords(1, 1)], + [Coords(0, 0), Coords(1, 0), Coords(0, 1), Coords(1, 1)], + [Coords(0, 0), Coords(1, 0), Coords(0, 1), Coords(1, 1)] ], [ // S - [Vector2(1, 0), Vector2(2, 0), Vector2(0, 1), Vector2(1, 1)], - [Vector2(1, 0), Vector2(1, 1), Vector2(2, 1), Vector2(2, 2)], - [Vector2(1, 1), Vector2(2, 1), Vector2(0, 2), Vector2(1, 2)], - [Vector2(0, 0), Vector2(0, 1), Vector2(1, 1), Vector2(1, 2)] + [Coords(1, 0), Coords(2, 0), Coords(0, 1), Coords(1, 1)], + [Coords(1, 0), Coords(1, 1), Coords(2, 1), Coords(2, 2)], + [Coords(1, 1), Coords(2, 1), Coords(0, 2), Coords(1, 2)], + [Coords(0, 0), Coords(0, 1), Coords(1, 1), Coords(1, 2)] ], [ // I - [Vector2(0, 1), Vector2(1, 1), Vector2(2, 1), Vector2(3, 1)], - [Vector2(2, 0), Vector2(2, 1), Vector2(2, 2), Vector2(2, 3)], - [Vector2(0, 2), Vector2(1, 2), Vector2(2, 2), Vector2(3, 2)], - [Vector2(1, 0), Vector2(1, 1), Vector2(1, 2), Vector2(1, 3)] + [Coords(0, 1), Coords(1, 1), Coords(2, 1), Coords(3, 1)], + [Coords(2, 0), Coords(2, 1), Coords(2, 2), Coords(2, 3)], + [Coords(0, 2), Coords(1, 2), Coords(2, 2), Coords(3, 2)], + [Coords(1, 0), Coords(1, 1), Coords(1, 2), Coords(1, 3)] ], [ // J - [Vector2(0, 0), Vector2(0, 1), Vector2(1, 1), Vector2(2, 1)], - [Vector2(1, 0), Vector2(2, 0), Vector2(1, 1), Vector2(1, 2)], - [Vector2(0, 1), Vector2(1, 1), Vector2(2, 1), Vector2(2, 2)], - [Vector2(1, 0), Vector2(1, 1), Vector2(0, 2), Vector2(1, 2)] + [Coords(0, 0), Coords(0, 1), Coords(1, 1), Coords(2, 1)], + [Coords(1, 0), Coords(2, 0), Coords(1, 1), Coords(1, 2)], + [Coords(0, 1), Coords(1, 1), Coords(2, 1), Coords(2, 2)], + [Coords(1, 0), Coords(1, 1), Coords(0, 2), Coords(1, 2)] ], [ // T - [Vector2(1, 0), Vector2(0, 1), Vector2(1, 1), Vector2(2, 1)], - [Vector2(1, 0), Vector2(1, 1), Vector2(2, 1), Vector2(1, 2)], - [Vector2(0, 1), Vector2(1, 1), Vector2(2, 1), Vector2(1, 2)], - [Vector2(1, 0), Vector2(0, 1), Vector2(1, 1), Vector2(1, 2)] + [Coords(1, 0), Coords(0, 1), Coords(1, 1), Coords(2, 1)], + [Coords(1, 0), Coords(1, 1), Coords(2, 1), Coords(1, 2)], + [Coords(0, 1), Coords(1, 1), Coords(2, 1), Coords(1, 2)], + [Coords(1, 0), Coords(0, 1), Coords(1, 1), Coords(1, 2)] ] ]; -List spawnPositionFixes = [Vector2(1, 1), Vector2(1, 1), Vector2(0, 1), Vector2(1, 1), Vector2(1, 1), Vector2(1, 1), Vector2(1, 1)]; +List spawnPositionFixes = [Coords(1, 1), Coords(1, 1), Coords(0, 1), Coords(1, 1), Coords(1, 1), Coords(1, 1), Coords(1, 1)]; const Map garbage = { "single": 0,