Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 209 additions & 0 deletions Opponent-logic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
# ♟️ How the AI Opponent Works

👉 Your computer opponent is **very simple**.
It’s not a real chess AI — it’s basically a **greedy + random bot**.

---

## 🧠 How the Computer Chooses Moves

The logic lives here:

```ruby
class ComputerPlayer
def play_turn(board, color)
```

This method decides **one move per turn**.

---

## 🔍 Step 1: Look at all your pieces

```ruby
our_pieces = board.pieces(color)
```

👉 The computer gets **all its pieces** (black pieces in your game).

---

## 🔍 Step 2: Look at enemy pieces

```ruby
enemy_pieces = board.pieces(color == :black ? :white : :black)
enemy_positions = enemy_pieces.map(&:pos)
```

👉 It finds:
- All your pieces
- Their positions on the board

---

## ⚔️ Step 3: Try to CAPTURE something

This is the **most important part**:

```ruby
piece_moves = piece.valid_moves
cap_moves = piece_moves.select { |move| enemy_positions.include?(move) }
```

👉 For each piece:
- Get all valid moves
- Filter moves that land on an enemy piece

➡️ Now it only considers **capture moves**.

---

## 💰 Step 4: Pick the MOST valuable capture

```ruby
best = cap_moves.max_by { |move| PIECE_VALUES[board[move].class] }
```

### Piece values:

```ruby
PIECE_VALUES = {
Queen => 9,
Rook => 5,
Knight => 3,
Bishop => 3,
Pawn => 1
}
```

👉 The computer prefers:

- Queen (9) 🔥
- Rook (5)
- Knight / Bishop (3)
- Pawn (1)

💡 **Example:**
If it can capture a pawn OR a queen → it picks the queen.

---

## 🏆 Step 5: Keep the BEST capture overall

```ruby
if val > best_val
best_move = [piece.pos, best]
best_val = val
end
```

👉 It compares all captures and keeps the **highest value move**.

---

## 🎲 Step 6: If no captures → RANDOM move

```ruby
if best_val.zero?
piece = our_pieces.reject { |p| p.valid_moves.empty? }.sample
move = piece.valid_moves.sample
```

👉 If it **can’t capture anything**, it:
- Picks a random piece
- Picks a random valid move

💀 This is why the AI sometimes looks *“dumb”*.

---

## 🚀 Step 7: Execute the move

```ruby
board.move(best_move[0], best_move[1], color)
```

👉 The move is played on the board.

---

## ♟️ Step 8: Pawn promotion (auto-queen)

```ruby
board.promote_pawn(Queen, color) if board.pawn_promotion
```

👉 If a pawn reaches the end:
- It **always becomes a Queen**

---

## 🧾 Final Output

```ruby
ComputerPlayer.translate_coords(best_move)
```

👉 Converts `[row, col]` back into chess notation like:

```
e2 e4
```

---

## 🧠 What kind of AI is this?

👉 This is called a **Greedy Algorithm**

Because it:
- Only looks at **immediate gain**
- Doesn’t think ahead
- Doesn’t simulate future moves

---

## ❌ What it does NOT do

Your AI does NOT:

- ❌ Look ahead (no minimax)
- ❌ Avoid traps
- ❌ Protect pieces
- ❌ Check for checkmate setups
- ❌ Evaluate board positions

---

## 🧪 Example Behavior

**Situation:**
- It can capture a pawn
- But that move loses its queen next turn

👉 It will STILL capture the pawn 😅

Because: “Pawn = value 1 → good enough”

---

## 💡 Why this is actually good (for learning)

This is a **perfect beginner AI** because:

- Easy to understand ✅
- Easy to improve ✅
- You can clearly see its weaknesses ✅

---

## 🚀 How to Improve It

Next step:

👉 Implement the **Minimax algorithm**

This would allow the AI to:
- Think ahead
- Evaluate positions
- Play MUCH stronger
90 changes: 73 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,82 @@
Chess
=======
![Chess](http://www.garrettjohnson.net/images/fulls/chessfull.png)
This is Chess, playable from the terminal, implemented in Ruby. To play against the computer, simply run chess.rb.
# ♟️ Ruby-Chess ♟️

To see human versus human, load chess.rb in irb or pry, and do Game.new(HumanPlayer.new,HumanPlayer.new).play
A simple terminal-based chess game written in **Ruby**.

Note that since the pieces are represented using unicode characters, your terminal needs to be using a font that supports them for the pieces to display correctly. Also, the colorize gem is used for some board markup, so make sure it is installed.
This project is a **fork** of an earlier open-source Ruby chess implementation.
I’ve updated it with **improved visuals, simplified color handling**, and a **clearer introduction for players**.

Highlights
======
The most complex logic is in the special rules.
---

The possibility of En Passant is tracked by the board object, with instance variables for the position that a pawn could move to with En Passant, and the Pawn object that would be captured by such a move. Whenever a pawn is scanning for legal moves, it compares a potential diagonal move to the board's en passant move.
## Features

Castling is relatively straightforward, if the king has not yet moved, it scans all of the conditions for castling (Rook hasn't moved, no pieces between King and Rook, King doesn't move through an attacked space), and allows the move if they are met.
- Fully functional chess rules (check, checkmate, stalemate, promotion)
- Play against a basic computer opponent
- ASCII-based board with Unicode chess pieces
- Simple and clean color scheme for easy readability
- Save and load games using YAML

To determine whether a move would be self-check, we create a duplicate of the board object, make the move, and look for attacks on the King.
---

Future Features
==========
Allow the use of Chess Notation for move inputs.
## How to Play

An all-around nicer interface.
### 1️⃣ Install Ruby
Make sure you have Ruby installed. You can check with:

Better AI!
ruby -v

If you don’t have it, install it from:
https://www.ruby-lang.org/en/downloads/




---

### 2️⃣ Run the Game
Clone the repository and start the game:

git clone https://github.com/david-marin-0xff/Ruby-Chess.git

cd Ruby-Chess

ruby chess.rb

<img width="922" height="365" alt="image" src="https://github.com/user-attachments/assets/afce8ddc-78db-4642-880b-402b073c10c0" />


---

### 3️⃣ Move Pieces
Moves are entered in standard chess notation, for example:
e2 e4
g8 f6

You can type:
save
at any time to save your current game.

<img width="822" height="535" alt="image" src="https://github.com/user-attachments/assets/70ec0d34-3692-4fec-a4f6-1185184d6d55" />


---

## Notes

This is a **learning and experimental fork**, created to explore Ruby, game logic, and terminal graphics.
It’s also a fun weekend project — not meant for competitive play, but to study how a chess engine and move validation work under the hood.

Learn how the “AI opponent” works: https://github.com/david-marin-0xff/Ruby-Chess/blob/master/Opponent-logic.md

---

## Credits

Original project by another open-source contributor. → https://github.com/reruns/chess
Forked, modified, and maintained by:
David Marín (https://github.com/david-marin-0xff)

---

## License

MIT License — free to use, modify, and share.
Loading