Improve offensive AI: wingers push forward and better passing logic

- Wingers now push forward past attack zone (+40 units) when team has possession to create passing options
- Added findTeammateCloserToGoal() method to prioritize passes to teammates in better scoring positions
- Puck handlers now pass to teammates closer to goal with 70% probability
- Enhanced team coordination and more realistic offensive positioning

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Pierre Wessman 2025-09-18 20:51:47 +02:00
parent f7cec84973
commit 1ea9657aa4

View File

@ -260,8 +260,15 @@ class Player {
} }
} }
// Check if any teammate is closer to goal for a better scoring position
const teammateCloserToGoal = this.findTeammateCloserToGoal(teammates, opponents, enemyGoal, distanceToGoal);
if (teammateCloserToGoal && Math.random() < 0.7) {
this.pass(puck, teammateCloserToGoal);
return;
}
// If under heavy pressure, look for a pass first // If under heavy pressure, look for a pass first
if (distanceToNearestOpponent < 60) { if (distanceToNearestOpponent < 100) {
const bestTeammate = this.findBestPassTarget(teammates, opponents); const bestTeammate = this.findBestPassTarget(teammates, opponents);
if (bestTeammate && Math.random() < 0.8) { if (bestTeammate && Math.random() < 0.8) {
this.pass(puck, bestTeammate); this.pass(puck, bestTeammate);
@ -474,13 +481,13 @@ class Player {
baseY = rink.centerY + (puck.position.y > rink.centerY ? -60 : 60); baseY = rink.centerY + (puck.position.y > rink.centerY ? -60 : 60);
break; break;
case 'LW': case 'LW':
// Left wing positions for cross-ice passes and wraparounds // Left wing pushes forward on their side for passing options
baseX = attackZone - 30; baseX = attackZone + 40; // Push forward past attack zone
baseY = rink.centerY - 140; baseY = rink.centerY - 140;
break; break;
case 'RW': case 'RW':
// Right wing positions for cross-ice passes and wraparounds // Right wing pushes forward on their side for passing options
baseX = attackZone - 30; baseX = attackZone + 40; // Push forward past attack zone
baseY = rink.centerY + 140; baseY = rink.centerY + 140;
break; break;
case 'LD': case 'LD':
@ -687,6 +694,58 @@ class Player {
return bestTarget; return bestTarget;
} }
/**
* Finds a teammate who is closer to the goal than the current puck carrier
* and has a clear passing lane for better scoring opportunities
* @param {Array} teammates - Array of teammate player objects
* @param {Array} opponents - Array of opponent players that might block the pass
* @param {Vector2} enemyGoal - Position of the opponent's goal
* @param {number} myDistanceToGoal - Current player's distance to goal
* @returns {Object|null} Best teammate closer to goal, or null if no good options
*/
findTeammateCloserToGoal(teammates, opponents, enemyGoal, myDistanceToGoal) {
let bestTarget = null;
let bestScore = -1;
teammates.forEach(teammate => {
// Skip goalies
if (teammate.role === 'G') return;
const teammateDistanceToGoal = teammate.position.distance(enemyGoal);
const distanceToTeammate = this.position.distance(teammate.position);
// Only consider teammates who are closer to goal and within reasonable passing distance
if (teammateDistanceToGoal >= myDistanceToGoal || distanceToTeammate < 50 || distanceToTeammate > 250) {
return;
}
// Check if pass is blocked by opponents
let blocked = false;
opponents.forEach(opponent => {
const lineToTeammate = teammate.position.subtract(this.position);
const lineToOpponent = opponent.position.subtract(this.position);
const angle = Math.abs(lineToTeammate.angle() - lineToOpponent.angle());
if (angle < 0.4 && this.position.distance(opponent.position) < distanceToTeammate) {
blocked = true;
}
});
if (!blocked) {
// Score based on how much closer to goal they are and their attributes
const goalAdvantage = myDistanceToGoal - teammateDistanceToGoal;
const score = (goalAdvantage * teammate.attributes.shooting) / distanceToTeammate;
if (score > bestScore) {
bestScore = score;
bestTarget = teammate;
}
}
});
return bestTarget;
}
/** /**
* Determines if this player is the closest non-goalie teammate to the puck * Determines if this player is the closest non-goalie teammate to the puck
* Used to decide who should chase loose pucks * Used to decide who should chase loose pucks