Skip to content

Add AI players with configurable strategies#67

Draft
durangogt with Copilot wants to merge 6 commits into
mainfrom
copilot/add-ai-players-strategies
Draft

Add AI players with configurable strategies#67
durangogt with Copilot wants to merge 6 commits into
mainfrom
copilot/add-ai-players-strategies

Conversation

Copilot AI commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

Implements AI opponents to enable solo play and AI vs AI simulation. The existing game_engine.py architecture (get_valid_moves() + execute_move()) provided a clean interface for AI integration.

Implementation

AI Strategy System

  • Base AIPlayer class with choose_move(game, dice_roll) -> Optional[int] interface
  • Three concrete strategies:
    • RandomStrategy (easy): Random selection from valid moves
    • AggressiveStrategy (medium): Scores moves by forward progress + aggravation potential
    • DefensiveStrategy (hard): Scores moves by safety + strategic positioning
  • Factory function create_ai_player(strategy_name, player_number, difficulty) for instantiation

Player Configuration

  • PlayerConfig class tracking player type (Human/AI) and strategy selection
  • PlayerSelectionScreen with pygame UI for interactive configuration
  • Toggle buttons for player type, dropdown for AI strategy selection

Game Modes

  • aggravation_ai.py launcher supporting three modes:
    • Interactive: Player selection screen → game start
    • Watch: --watch flag sets all players to AI
    • Headless: --headless flag runs terminal-based simulation

Usage

# Programmatic usage
from ai_player import create_ai_player
from game_engine import AggravationGame

game = AggravationGame()
ai = create_ai_player('aggressive', player_number=1)

dice_roll = game.roll_dice()
move = ai.choose_move(game, dice_roll)  # Returns marble index or -1 for home

if move is not None:
    if move == -1:
        game.remove_from_home(1)
    else:
        game.execute_move(1, move, dice_roll)
# CLI usage
python aggravation_ai.py              # Interactive player selection
python aggravation_ai.py --watch      # All AI players
python aggravation_ai.py --headless   # Terminal simulation
python demo_ai.py                     # Strategy demonstration

Player Selection UI

Player Selection Screen

Files Added

  • ai_player.py - Strategy implementations (410 lines)
  • player_selection.py - Configuration UI (347 lines)
  • aggravation_ai.py - Game launcher (245 lines)
  • test_ai_player.py - Test suite (19 tests, all passing)
  • demo_ai.py - Interactive demo (135 lines)

Limitations

  • GUI mode uses simplified text status display; full board visualization with AI moves not implemented
  • Human vs AI mixed mode requires additional game loop integration for human input
Original prompt

This section details on the original issue you should resolve

<issue_title>Add AI Players with Configurable StrategiesLabel</issue_title>
<issue_description>Issue 1

Title: Add AI Players with Configurable StrategiesLabel: featureBody:

Right now all 4 players are human-controlled. Adding AI opponents with selectable strategies (aggressive, defensive, shortcut-hunter, random) would make the game fun to play solo.

The game_engine.py architecture is already perfectly set up for this — get_valid_moves() + execute_move() is a clean AI interface.

Scope:

• Implement at least 3 AI strategy classes (random, aggressive, defensive)

• Add difficulty levels (easy/medium/hard)

• Support “watch AI vs AI” simulation mode

• Player selection screen to choose human vs AI for each seat</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 5 commits February 11, 2026 05:28
Co-authored-by: durangogt <10979447+durangogt@users.noreply.github.com>
Co-authored-by: durangogt <10979447+durangogt@users.noreply.github.com>
Co-authored-by: durangogt <10979447+durangogt@users.noreply.github.com>
…dling

Co-authored-by: durangogt <10979447+durangogt@users.noreply.github.com>
Co-authored-by: durangogt <10979447+durangogt@users.noreply.github.com>
Copilot AI changed the title [WIP] Add AI players with configurable strategies Add AI players with configurable strategies Feb 11, 2026
Copilot AI requested a review from durangogt February 11, 2026 05:37
@durangogt
durangogt requested review from Copilot and removed request for durangogt February 22, 2026 01:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds AI player capabilities to the Aggravation board game, enabling solo play and AI vs AI simulation. The implementation leverages the existing game engine's get_valid_moves() and execute_move() interface to provide three distinct AI strategies with different difficulty levels.

Changes:

  • Adds three AI strategies (Random/Easy, Aggressive/Medium, Defensive/Hard) with distinct decision-making algorithms
  • Implements interactive player selection screen for configuring Human vs AI players
  • Provides three game modes: interactive player selection, watch AI vs AI, and headless simulation
  • Includes comprehensive test suite with 19 tests covering all strategies and integration scenarios
  • Updates documentation with detailed usage examples and strategy descriptions

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
ai_player.py Implements base AIPlayer class and three concrete strategies (Random, Aggressive, Defensive) with move selection logic
player_selection.py Provides pygame-based UI for interactive player type and strategy configuration
aggravation_ai.py Main launcher supporting interactive, watch, and headless game modes with AI integration
test_ai_player.py Comprehensive test suite with 19 tests covering factory creation, strategy behavior, and integration
demo_ai.py Interactive demonstration script showing AI decision-making and move execution
README.md Documentation updates with AI feature description, usage examples, and strategy explanations
AI_IMPLEMENTATION.md Detailed implementation summary documenting architecture, requirements, and limitations
screenshots/player_selection.png Screenshot of the player selection UI (binary file)

Comment thread ai_player.py
Comment on lines +300 to +342
def _calculate_safety_score(self, game: AggravationGame, position: Tuple[int, int]) -> float:
"""Calculate how safe a position is (higher = safer)."""
# Positions in final home are completely safe
if position in PLAYER_FINAL_HOMES[self.player_number]:
return 100

# Positions in home stretch are safer
if position in PLAYER_HOME_STRETCHES[self.player_number]:
return 50

# Check if any opponent could land on this position
danger_score = 30 # Base safety score

# Check all opponent marbles to see if they could reach this position
for opp_player in range(1, 5):
if opp_player == self.player_number:
continue

opp_data = game._get_player_data(opp_player)
opp_marbles = opp_data['marbles']

for opp_marble in opp_marbles:
if opp_marble is None or opp_marble == (None, None):
continue

# Check if opponent could reach this position with any dice roll (1-6)
for dice in range(1, 7):
test_pos = opp_marble
for _ in range(dice):
try:
test_pos = game.get_next_position(test_pos[0], test_pos[1])
except (AssertionError, IndexError):
# get_next_position uses assertions for validation
# TODO: game_engine should raise specific exceptions instead
break
if test_pos is None:
break

if test_pos == position:
danger_score -= 10 # Reduce safety score
break # No need to check other dice rolls for this marble

return max(0, danger_score)

Copilot AI Feb 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _calculate_safety_score method has O(n×m×6×d) complexity where n=number of opponents, m=marbles per player, d=max dice value. For each valid move being evaluated, this checks if any opponent could reach the position with any dice roll (1-6). While functional, this could be slow when evaluating multiple moves. Consider optimizing if performance becomes an issue, perhaps by caching threat calculations or using a simpler heuristic.

Copilot uses AI. Check for mistakes.
Comment thread aggravation_ai.py
"""

import sys
import os

Copilot AI Feb 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The os module is imported but never used in this file. Consider removing this unused import.

Suggested change
import os

Copilot uses AI. Check for mistakes.
Comment thread aggravation_ai.py
import sys
import os
import random
import time

Copilot AI Feb 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The time module is imported but never used in this file. The code uses pygame.time.wait() instead. Consider removing this unused import.

Suggested change
import time

Copilot uses AI. Check for mistakes.
Comment thread aggravation_ai.py

import sys
import os
import random

Copilot AI Feb 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The random module is imported but never used in this file. Consider removing this unused import.

Suggested change
import random

Copilot uses AI. Check for mistakes.
Comment thread aggravation_ai.py
result = game.execute_move(current_player, move, dice_roll)
if result['success']:
print(f" Moved marble {move} from {result['old_position']} to {result['new_position']}")
if result.get('aggravation'):

Copilot AI Feb 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key name in the result dictionary doesn't match the game engine's return value. The execute_move function in game_engine.py returns 'aggravated_opponent' as the key (see game_engine.py:514, 563), but this code checks for 'aggravation'. This will always be falsy, preventing the aggravation message from being displayed.

Suggested change
if result.get('aggravation'):
if result.get('aggravated_opponent'):

Copilot uses AI. Check for mistakes.
Comment thread aggravation_ai.py
result = game.execute_move(current_player, move, dice_roll)
if result['success']:
msg = f"Player {current_player}: Moved marble {move}"
if result.get('aggravation'):

Copilot AI Feb 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key name in the result dictionary doesn't match the game engine's return value. The execute_move function in game_engine.py returns 'aggravated_opponent' as the key (see game_engine.py:514, 563), but this code checks for 'aggravation'. This will always be falsy, preventing the aggravation message from being displayed.

Suggested change
if result.get('aggravation'):
if result.get('aggravated_opponent'):

Copilot uses AI. Check for mistakes.
Comment thread demo_ai.py
print(f" AI moved marble {move}")
print(f" From: {result['old_position']}")
print(f" To: {result['new_position']}")
if result.get('aggravation'):

Copilot AI Feb 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key name in the result dictionary doesn't match the game engine's return value. The execute_move function in game_engine.py returns 'aggravated_opponent' as the key (see game_engine.py:514, 563), but this code checks for 'aggravation'. This will always be falsy, preventing the aggravation message from being displayed.

Suggested change
if result.get('aggravation'):
if result.get('aggravated_opponent'):

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add AI Players with Configurable StrategiesLabel

3 participants