diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c828121 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*.sh linguist-vendored +*.py linguist-vendored \ No newline at end of file diff --git a/pommer.py b/pommer.py new file mode 100644 index 0000000..745403d --- /dev/null +++ b/pommer.py @@ -0,0 +1,591 @@ +#!/usr/bin/env python3 + +""" +``` POMMER.PY ``` + +!:: THIS IS PROPRIETARY SOFTWARE DO NOT DISTRIBUTE TO OUTSIDERS ::! + +This Python File is distributed with every Kotlin / Java Plugin Repository! +If you find this to be confusing to use look at the Documentation in "rattatwinko/pommer" + +Run this Script with Python 3.11 ; 3.9 + +This works with Gradle and Maven ; other Branch is for reliablitiy ; this one is for "Support" with larger *commercial* Builds + + +!:: Maven Building with the Master Branch ( this Version ) is unstable! The Building Test is placed "rattatwinko/mavenprobe"!! ::! + +""" + +import os +import xml.etree.ElementTree as ET +import re +from pathlib import Path +import argparse +import glob +import json + + +def parse_pom_xml(pom_path): + """ + Parse a pom.xml file and extract relevant information + """ + try: + print(f"Parsing POM file: {pom_path}") + + # Register the default namespace + ET.register_namespace('', "http://maven.apache.org/POM/4.0.0") + + # Parse the XML file + tree = ET.parse(pom_path) + root = tree.getroot() + + # Define namespace for easier XPath queries + ns = {'mvn': "http://maven.apache.org/POM/4.0.0"} + + # Extract project info + artifact_id = root.find('./mvn:artifactId', ns).text + group_id = root.find('./mvn:groupId', ns).text if root.find('./mvn:groupId', ns) is not None else "unknown" + version = root.find('./mvn:version', ns).text if root.find('./mvn:version', ns) is not None else "unknown" + name = root.find('./mvn:name', ns).text if root.find('./mvn:name', ns) is not None else artifact_id + + # Extract Java version + java_version_elem = root.find('./mvn:properties/mvn:java.version', ns) + java_version = java_version_elem.text if java_version_elem is not None else "17" # Default to Java 17 if not specified + + # Extract packaging type (default to jar if not specified) + packaging = root.find('./mvn:packaging', ns) + packaging = packaging.text if packaging is not None else "jar" + + # Check if Kotlin is used + kotlin_version_elem = root.find('./mvn:properties/mvn:kotlin.version', ns) + kotlin_version = kotlin_version_elem.text if kotlin_version_elem is not None else None + + # Check for Kotlin plugin or dependency + kotlin_plugin = None + kotlin_dep = None + + # Check for Kotlin plugin + plugins = root.findall('.//mvn:plugin', ns) + for plugin in plugins: + plugin_group = plugin.find('./mvn:groupId', ns) + if plugin_group is not None and plugin_group.text == 'org.jetbrains.kotlin': + kotlin_plugin = plugin + break + + # Check for Kotlin dependency + deps = root.findall('.//mvn:dependency', ns) + for dep in deps: + dep_group = dep.find('./mvn:groupId', ns) + dep_artifact = dep.find('./mvn:artifactId', ns) + if (dep_group is not None and dep_group.text == 'org.jetbrains.kotlin' and + dep_artifact is not None and 'kotlin-stdlib' in dep_artifact.text): + kotlin_dep = dep + break + + # Determine if this is a Kotlin project + is_kotlin = kotlin_version is not None or kotlin_plugin is not None or kotlin_dep is not None + + # Check for source directories + source_dir = None + source_dirs = root.findall('.//mvn:sourceDirectory', ns) + if source_dirs: + source_dir = source_dirs[0].text + + # Check for default goal (to use the same command as IntelliJ) + default_goal = None + default_goal_elem = root.find('./mvn:build/mvn:defaultGoal', ns) + if default_goal_elem is not None: + default_goal = default_goal_elem.text + + return { + "artifact_id": artifact_id, + "group_id": group_id, + "version": version, + "name": name, + "java_version": java_version, + "packaging": packaging, + "is_kotlin": is_kotlin, + "kotlin_version": kotlin_version, + "source_dir": source_dir, + "default_goal": default_goal, + "pom_path": pom_path, + "build_system": "maven" + } + except Exception as e: + print(f"Error parsing {pom_path}: {e}") + return None + + +def parse_gradle_file(gradle_path): + """ + Parse a build.gradle or build.gradle.kts file and extract relevant information + """ + try: + print(f"Parsing Gradle file: {gradle_path}") + + # Read the file content + with open(gradle_path, 'r') as f: + content = f.read() + + # Determine if it's a Kotlin DSL file + is_kotlin_dsl = gradle_path.endswith('.kts') + + # Extract group, version and project name + group_match = re.search(r'group\s*=\s*[\'"]([^\'"]+)[\'"]', content) + group_id = group_match.group(1) if group_match else "unknown" + + version_match = re.search(r'version\s*=\s*[\'"]([^\'"]+)[\'"]', content) + version = version_match.group(1) if version_match else "unknown" + + # Check settings.gradle for project name + settings_path = os.path.join(os.path.dirname(gradle_path), "settings.gradle") + settings_path_kts = os.path.join(os.path.dirname(gradle_path), "settings.gradle.kts") + + artifact_id = "unknown" + name = "unknown" + + # Here I was on fucking crack? This is fucking crazy! + # Anyways Here it checks the artifacting settings for Gradle (kts) + if os.path.exists(settings_path): + with open(settings_path, 'r') as f: + settings_content = f.read() + root_project_match = re.search(r'rootProject\.name\s*=\s*[\'"]([^\'"]+)[\'"]', settings_content) + if root_project_match: + artifact_id = root_project_match.group(1) + name = artifact_id + elif os.path.exists(settings_path_kts): + with open(settings_path_kts, 'r') as f: + settings_content = f.read() + root_project_match = re.search(r'rootProject\.name\s*=\s*[\'"]([^\'"]+)[\'"]', settings_content) + if root_project_match: + artifact_id = root_project_match.group(1) + name = artifact_id + + # If no name found in settings.gradle, use directory name + if artifact_id == "unknown": + artifact_id = os.path.basename(os.path.dirname(gradle_path)) + name = artifact_id + + # Check for Java version + java_version = "17" # Default to Java 17 + java_version_match = re.search(r'sourceCompatibility\s*=\s*[\'"]*JavaVersion\.VERSION_(\d+)[\'"]*', content) + if java_version_match: + java_version = java_version_match.group(1) + else: + # Alternative pattern: sourceCompatibility = '11' + alt_java_match = re.search(r'sourceCompatibility\s*=\s*[\'"](\d+)[\'"]', content) + if alt_java_match: + java_version = alt_java_match.group(1) + else: + # Look for toolchain configuration + toolchain_match = re.search(r'toolchain\s*{[^}]*languageVersion\s*=\s*JavaLanguageVersion\s*\.\s*of\s*\(\s*(\d+)\s*\)', content, re.DOTALL) + if toolchain_match: + java_version = toolchain_match.group(1) + + # Check if Kotlin is used + kotlin_plugin_match = re.search(r'(id\s*\(\s*[\'"]kotlin[\'"])|(id\s*[\'"]org\.jetbrains\.kotlin)', content) + kotlin_version_match = re.search(r'kotlin\s*version\s*[\'"]([^\'"]+)[\'"]', content) + is_kotlin = bool(kotlin_plugin_match) or bool(kotlin_version_match) or is_kotlin_dsl + + kotlin_version = kotlin_version_match.group(1) if kotlin_version_match else None + + # Check for application plugin + is_application = bool(re.search(r'id\s*\(\s*[\'"]application[\'"]', content)) + + return { + "artifact_id": artifact_id, + "group_id": group_id, + "version": version, + "name": name, + "java_version": java_version, + "packaging": "jar" if not is_application else "application", + "is_kotlin": is_kotlin, + "kotlin_version": kotlin_version, + "source_dir": None, # Gradle uses conventional source dirs + "default_goal": None, # Gradle doesn't have default goals like Maven + "gradle_path": gradle_path, + "is_kotlin_dsl": is_kotlin_dsl, + "build_system": "gradle" + } + except Exception as e: + print(f"Error parsing {gradle_path}: {e}") + return None + + +def generate_maven_workflow(pom_infos): + """ + Generate a Gitea workflow YAML file for Maven projects + """ + if not pom_infos: + print("No valid Maven POM files found") + return None + + # Get the highest Java version required + java_version = max([info["java_version"] for info in pom_infos]) + + # Check if any project uses Kotlin + uses_kotlin = any(info["is_kotlin"] for info in pom_infos) + + # Kotlin version (if any) + kotlin_version = None + for info in pom_infos: + if info["kotlin_version"]: + kotlin_version = info["kotlin_version"] + break + + # Construct the workflow content + workflow_content = f"""name: Maven Build + +on: + push: + branches: [ main, master, dev ] + pull_request: + branches: [ main, master ] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK {java_version} + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '{java_version}' + cache: 'maven' + + - name: Install Maven + run: | + if ! command -v mvn &> /dev/null; then + echo "Maven not found, installing..." + sudo apt-get update + sudo apt-get install -y maven + fi + mvn --version + + - name: Debug Info + run: | + echo "Current workspace directory: $GITHUB_WORKSPACE" + echo "Current directory: $(pwd)" + echo "Project structure:" + find . -type f -name "*.kt" | sort + find . -type f -name "pom.xml" + echo "Maven version: $(mvn --version)" +""" + + # Add individual build steps for each POM + for i, info in enumerate(pom_infos): + # Determine the Maven command to use (same as the default goal if specified) + maven_command = "clean package" + if info["default_goal"]: + maven_command = info["default_goal"] + + relative_pom_path = info["pom_path"] + + workflow_content += f""" + - name: Build {info["name"]} ({info["artifact_id"]}) + run: | + echo "Building {info["artifact_id"]}" + echo "Current directory: $(pwd)" + # Run Maven build directly using the POM file path + mvn -B {maven_command} -f "{relative_pom_path}" -Dmaven.compiler.failOnError=true +""" + + # Add artifact upload step + workflow_content += f""" + - name: Upload {info["artifact_id"]} artifact + uses: actions/upload-artifact@v3 + with: + name: {info["artifact_id"]} + path: | + {os.path.dirname(relative_pom_path)}/target/{info['artifact_id']}-*.jar + {os.path.dirname(relative_pom_path)}/target/*.jar + if-no-files-found: warn +""" + + return workflow_content + + +def generate_gradle_workflow(gradle_infos): + """ + Generate a Gitea workflow YAML file for Gradle projects + """ + if not gradle_infos: + print("No valid Gradle files found") + return None + + # Get the highest Java version required + java_version = max([info["java_version"] for info in gradle_infos]) + + # Check if any project uses Kotlin + uses_kotlin = any(info["is_kotlin"] for info in gradle_infos) + + # Kotlin version (if any) + kotlin_version = None + for info in gradle_infos: + if info["kotlin_version"]: + kotlin_version = info["kotlin_version"] + break + + # Construct the workflow content + workflow_content = f"""name: Gradle Build + +on: + push: + branches: [ main, master, dev ] + pull_request: + branches: [ main, master ] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK {java_version} + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '{java_version}' + cache: 'gradle' + + - name: Grant execute permission for gradlew + run: | + find . -name gradlew -type f -exec chmod +x {{}} \; + + - name: Debug Info + run: | + echo "Current workspace directory: $GITHUB_WORKSPACE" + echo "Current directory: $(pwd)" + echo "Project structure:" + find . -type f -name "*.kt" | sort + find . -type f -name "build.gradle*" + if [ -f ./gradlew ]; then + ./gradlew --version + else + echo "No wrapper found, will use system gradle" + gradle --version + fi +""" + + # Add individual build steps for each Gradle project + for i, info in enumerate(gradle_infos): + project_dir = os.path.dirname(info["gradle_path"]) + has_wrapper = os.path.exists(os.path.join(project_dir, "gradlew")) + gradle_command = f"{os.path.join(project_dir, 'gradlew')}" if has_wrapper else "gradle" + + workflow_content += f""" + - name: Build {info["name"]} ({info["artifact_id"]}) + working-directory: {project_dir} + run: | + echo "Building {info["artifact_id"]}" + echo "Current directory: $(pwd)" + # Run Gradle build + {"./gradlew" if has_wrapper else "gradle"} build +""" + + # Add artifact upload step + workflow_content += f""" + - name: Upload {info["artifact_id"]} artifact + uses: actions/upload-artifact@v3 + with: + name: {info["artifact_id"]} + path: | + {project_dir}/build/libs/*.jar + {project_dir}/app/build/libs/*.jar + {project_dir}/build/distributions/*.zip + {project_dir}/app/build/distributions/*.zip + if-no-files-found: warn +""" + + return workflow_content + + +def find_pom_files(base_dir="."): + """Find all pom.xml files in the given directory and subdirectories""" + return glob.glob(f"{base_dir}/**/pom.xml", recursive=True) + + +def find_gradle_files(base_dir="."): + """Find all build.gradle and build.gradle.kts files in the given directory and subdirectories""" + gradle_files = glob.glob(f"{base_dir}/**/build.gradle", recursive=True) + kotlin_gradle_files = glob.glob(f"{base_dir}/**/build.gradle.kts", recursive=True) + return gradle_files + kotlin_gradle_files + + +def generate_build_script(project_infos): + """Generate a universal build script for either Maven or Gradle projects""" + + maven_projects = [p for p in project_infos if p["build_system"] == "maven"] + gradle_projects = [p for p in project_infos if p["build_system"] == "gradle"] + + script = """#!/bin/bash +# Universal build script for Maven and Gradle projects + +echo "Current directory: $(pwd)" +""" + + if maven_projects: + script += """ +# Check if Maven is installed +if ! command -v mvn &> /dev/null; then + echo "Maven not found, installing..." + sudo apt-get update + sudo apt-get install -y maven +fi + +echo "Maven version: $(mvn --version)" +""" + + for project in maven_projects: + script += f""" +echo "Building Maven project: {project['name']}" +mvn clean package -f "{project['pom_path']}" +""" + + if gradle_projects: + script += """ +# Check for Gradle or Gradle Wrapper +""" + for project in gradle_projects: + project_dir = os.path.dirname(project["gradle_path"]) + has_wrapper = os.path.exists(os.path.join(project_dir, "gradlew")) + + if has_wrapper: + script += f""" +echo "Building Gradle project using wrapper: {project['name']}" +cd "{project_dir}" +chmod +x ./gradlew +./gradlew build +cd - > /dev/null +""" + else: + script += f""" +echo "Building Gradle project using system Gradle: {project['name']}" +# Install Gradle if not available +if ! command -v gradle &> /dev/null; then + echo "Gradle not found, installing..." + sudo apt-get update + sudo apt-get install -y gradle +fi +cd "{project_dir}" +gradle build +cd - > /dev/null +""" + + script += """ +echo "Build complete. Build artifacts should be in their respective target/ or build/libs/ directories." +""" + return script + + +def main(): + parser = argparse.ArgumentParser(description='Generate Gitea workflow for Maven/Gradle/Kotlin projects') + parser.add_argument('--dir', '-d', default='.', help='Base directory to search for project files') + parser.add_argument('--specific-pom', '-p', help='Path to a specific pom.xml file to process') + parser.add_argument('--specific-gradle', '-g', help='Path to a specific build.gradle file to process') + parser.add_argument('--output-json', '-j', action='store_true', help='Output project info as JSON as well') + args = parser.parse_args() + + # Find project files + pom_files = [] + gradle_files = [] + + if args.specific_pom: + pom_files = [args.specific_pom] + else: + pom_files = find_pom_files(args.dir) + + if args.specific_gradle: + gradle_files = [args.specific_gradle] + else: + gradle_files = find_gradle_files(args.dir) + + if not pom_files and not gradle_files: + print(f"No pom.xml or build.gradle files found in {args.dir}") + return + + print(f"Found {len(pom_files)} pom.xml files and {len(gradle_files)} Gradle files") + + # Parse all project files + project_infos = [] + + # Parse Maven files + for pom_file in pom_files: + info = parse_pom_xml(pom_file) + if info: + project_infos.append(info) + + # Parse Gradle files + for gradle_file in gradle_files: + info = parse_gradle_file(gradle_file) + if info: + project_infos.append(info) + + if not project_infos: + print("No valid project files could be parsed") + return + + # Count by build system + maven_count = sum(1 for p in project_infos if p["build_system"] == "maven") + gradle_count = sum(1 for p in project_infos if p["build_system"] == "gradle") + + # Create the .gitea/workflows directory if it doesn't exist + workflow_dir = Path(".gitea/workflows") + workflow_dir.mkdir(parents=True, exist_ok=True) + + # Generate and write workflow files for each build system + if maven_count > 0: + maven_infos = [p for p in project_infos if p["build_system"] == "maven"] + maven_workflow = generate_maven_workflow(maven_infos) + if maven_workflow: + maven_workflow_file = workflow_dir / "maven_build.yaml" + with open(maven_workflow_file, "w") as f: + f.write(maven_workflow) + print(f"Gitea Maven workflow generated at: {maven_workflow_file}") + + if gradle_count > 0: + gradle_infos = [p for p in project_infos if p["build_system"] == "gradle"] + gradle_workflow = generate_gradle_workflow(gradle_infos) + if gradle_workflow: + gradle_workflow_file = workflow_dir / "gradle_build.yaml" + with open(gradle_workflow_file, "w") as f: + f.write(gradle_workflow) + print(f"Gitea Gradle workflow generated at: {gradle_workflow_file}") + + # Generate a universal build script + build_script = generate_build_script(project_infos) + with open("build.sh", "w") as f: + f.write(build_script) + os.chmod("build.sh", 0o755) + print(f"Universal build script generated at: build.sh") + + # Print summary of detected projects + print("\nDetected projects:") + # What the actuall fuck is going on here? Whoever reads this may God be with you! + for info in project_infos: + kotlin_info = "with Kotlin" if info["is_kotlin"] else "Java only" + if info["build_system"] == "maven": + build_command = info["default_goal"] if info["default_goal"] else "clean package" + print(f"- {info['name']} ({info['artifact_id']}): Maven, {kotlin_info}, Java {info['java_version']}, build: {build_command}") + else: + dsl_info = "Kotlin DSL" if info.get("is_kotlin_dsl") else "Groovy DSL" + print(f"- {info['name']} ({info['artifact_id']}): Gradle ({dsl_info}), {kotlin_info}, Java {info['java_version']}") + + # Export as JSON if requested + if args.output_json: + with open("project_info.json", "w") as f: + json.dump(project_infos, f, indent=2) + print(f"Project information exported to project_info.json") + +# Run script! +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/src/main/java/org/hamiltoniansnakeai/HamiltonianSnakeAI.java b/src/main/java/org/hamiltoniansnakeai/HamiltonianSnakeAI.java index 95656c2..ebe4f58 100644 --- a/src/main/java/org/hamiltoniansnakeai/HamiltonianSnakeAI.java +++ b/src/main/java/org/hamiltoniansnakeai/HamiltonianSnakeAI.java @@ -466,31 +466,50 @@ public class HamiltonianSnakeAI extends JPanel implements ActionListener { scoreLabel.setText("Score: " + score); } } + private Point findDirectPathToFood(Point head, List possibleMoves) { + // Find moves that directly reduce distance to food + Point bestMove = null; + int minDistance = Integer.MAX_VALUE; + + for (Point move : possibleMoves) { + int dist = estimateDistance(move, food); + if (dist < minDistance && !willCollideImmediately(move)) { + minDistance = dist; + bestMove = move; + } + } + + return bestMove; + } + private Point getNextMove(Point head) { List possibleMoves = getSafeMoves(head); if (possibleMoves.isEmpty()) { - return head; // No safe moves available (will trigger game over) + return head; // No safe moves available } - // 1. First priority: Don't die next turn + // 1. If food is very close and safe, go for it immediately + if (estimateDistance(head, food) <= 3) { + Point foodMove = findDirectPathToFood(head, possibleMoves); + if (foodMove != null) { + return foodMove; + } + } + + // 2. Filter out immediately deadly moves possibleMoves = filterImmediatelyDeadlyMoves(possibleMoves); if (possibleMoves.isEmpty()) return head; - // 2. Second priority: Don't create future traps - possibleMoves = filterFutureTraps(possibleMoves, 3); // Look 3 moves ahead - if (possibleMoves.isEmpty()) return head; - - // 3. If food is reachable and safe, go for it + // 3. If food is reachable via safe path, prioritize it Point foodPathMove = findSafePathToFood(head, possibleMoves); - if (foodPathMove != null) { + if (foodPathMove != null && !willCreateTrap(foodPathMove)) { return foodPathMove; } // 4. Follow Hamiltonian cycle with safety checks return followSuperSafeHamiltonianCycle(head, possibleMoves); } - private List filterImmediatelyDeadlyMoves(List moves) { List safeMoves = new ArrayList<>(); for (Point move : moves) { @@ -593,29 +612,35 @@ public class HamiltonianSnakeAI extends JPanel implements ActionListener { return bestMove; } + private boolean willCreateTrap(Point move) { + // Simulate the move + List simulatedBody = new ArrayList<>(snake.getBody()); + simulatedBody.add(0, move); + simulatedBody.remove(simulatedBody.size() - 1); + + // Check if this would leave enough space + int reachable = countReachableCells(move, new HashSet<>(simulatedBody)); + return reachable < snake.getLength() * 0.5; // Adjust threshold as needed + } + private Point followSuperSafeHamiltonianCycle(Point head, List possibleMoves) { int currentIndex = hamiltonianPath[head.y][head.x]; - int nextIndex = (currentIndex + 1) % (gridSize * gridSize); - // Find the safest move along the cycle - Point bestMove = null; - int bestSafetyScore = -1; - - for (Point move : possibleMoves) { + // Sort moves by how much they progress along the cycle + possibleMoves.sort(Comparator.comparingInt(move -> { int moveIndex = hamiltonianPath[move.y][move.x]; - int cycleProgress = (moveIndex - currentIndex + gridSize * gridSize) % (gridSize * gridSize); + return (moveIndex - currentIndex + gridSize * gridSize) % (gridSize * gridSize); + })); - // Calculate safety score (higher is better) - int safetyScore = (gridSize * gridSize - cycleProgress) + countSafeExits(move, new HashSet<>(snake.getBody())); - - if (safetyScore > bestSafetyScore || - (safetyScore == bestSafetyScore && cycleProgress < (gridSize * gridSize) / 2)) { - bestSafetyScore = safetyScore; - bestMove = move; + // Return the move that makes most progress while being safe + for (Point move : possibleMoves) { + if (!willCreateTrap(move)) { + return move; } } - return bestMove != null ? bestMove : possibleMoves.get(0); + // Fallback to first possible move if all would create traps + return possibleMoves.get(0); } private Point findOptimalPathToFood(Point head, List possibleMoves) { @@ -982,4 +1007,12 @@ class Snake { public boolean contains(Point point) { return body.contains(point); } + + public int getGridSize() { + return gridSize; + } + + public void setGridSize(int gridSize) { + this.gridSize = gridSize; + } } \ No newline at end of file