machinelearning.pablodiaz.eu · pablodiaz.eu
Juego tipo Columns con IA heurística (Universidad de Jaén, 2000/2001). Port Python · Updated 2026.
# Cómo aplicamos Machine Learning en Columns AI
> Documento educativo sobre la inteligencia artificial del proyecto original (C, 2000/2001).
> **Updated 2026** — port Python, pygame y documentación ampliada.
> Autores originales: **Pablo Jesús Díaz Ruiz** y **Juan Manuel Medina Martínez**.
---
## 1. ¿De qué trata este proyecto?
**Columns** es un juego de puzzle en el que caen columnas de tres gemas de colores. El jugador (o la IA) elige **dónde colocar** cada columna y **cómo rotarla** antes de que caiga. Cuando se alinean tres o más gemas del mismo color en fila, columna o diagonal, desaparecen y las gemas superiores caen — igual que en el clásico *Columns* de Sega.
La parte de **inteligencia artificial** no controla al humano: la IA juega sola, eligiendo la mejor columna y la mejor rotación en cada turno.
---
## 2. ¿Es realmente Machine Learning?
Aquí conviene ser precisos, porque es una lección importante:
| Lo que dice el nombre del proyecto | Lo que hace el código |
|---|---|
| "Machine Learning" | **Sistema experto basado en reglas** |
| Aprendizaje por refuerzo (mencionado en comentarios futuros) | **No implementado** en el código original |
| Redes neuronales (mencionado en el README) | **No implementado** en el código original |
El código **no entrena un modelo** con datos históricos. En cambio, implementa un **clasificador de patrones heurístico**: para cada columna del tablero, extrae *features* (características) y asigna una **prioridad numérica**. La columna con menor prioridad gana.
En el contexto académico de 2000, esto se enseñaba como introducción a la IA porque comparte ideas clave del ML:
1. **Extracción de características** (*feature engineering*)
2. **Clasificación** (asignar una etiqueta de prioridad 1–6)
3. **Función de decisión** (elegir el mínimo)
4. **Tres niveles de complejidad** (estrategias básica, intermedia y avanzada)
Piensa en ello como un **árbol de decisiones escrito a mano**, no como un modelo que aprende de la experiencia.
---
## 3. Arquitectura de la IA
```
┌─────────────────────────────────────────────────────────┐
│ PIEZA ACTUAL │
│ (bola1, bola2, bola3) │
└────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ EVALUAR CADA COLUMNA (0-9) │
│ Para cada hueco libre en la columna: │
│ • Leer gemas debajo, a los lados y en diagonal │
│ • Comparar con colores de la pieza │
│ • Asignar prioridad 1-6 │
└────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ ELEGIR COLUMNA (menor prioridad gana) │
└────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ ROTAR PIEZA (mover_ia) según tipo de patrón │
└────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ COLOCAR → ELIMINAR TRÍOS → GRAVEDAD → REPETIR │
└─────────────────────────────────────────────────────────┘
```
---
## 4. Las seis prioridades (el "modelo" de clasificación)
Cada columna recibe un número del **1** (mejor) al **6** (peor):
| Prioridad | Nombre | Qué detecta | Ejemplo |
|:---:|---|---|---|
| **1** | Caída vertical | Dos gemas iguales en la pieza caen sobre una gema del mismo color | Pieza `[R,R,V]` sobre una roja → formará columna de 3 rojas |
| **2** | Apilar | Debajo del hueco hay ya 2 gemas iguales del color de la pieza | Hueco sobre `[A,A]` y la pieza contiene azul |
| **3** | Fila horizontal | Dos gemas iguales a izquierda/derecha del hueco coinciden con la pieza | `[V,_,V]` + pieza con verde en el hueco |
| **4** | Diagonal izquierda | Patrón diagonal ↙ con dos gemas iguales | |
| **5** | Diagonal derecha | Patrón diagonal ↘ con dos gemas iguales | |
| **6** | Sin patrón | No se encontró combinación favorable | Se elige la primera columna libre |
**Regla de decisión:** `columna_ganadora = argmin(prioridades)`
Esto es equivalente a un clasificador multiclase donde las clases están **ordenadas por utilidad**.
---
## 5. Las tres estrategias (niveles de IA)
El menú original permitía elegir entre tres estrategias. Cada una activa más patrones:
### Estrategia 1 — Básica (`buscar_hueco_BASICO`)
- Solo prioridades **1** y **2** (columnas verticales).
- Ignora filas y diagonales.
- **Comportamiento:** la IA busca apilar gemas verticalmente.
- **Analogía ML:** modelo simple con pocas features; menos overfitting al contexto, pero menos capacidad.
### Estrategia 2 — Intermedia (`buscar_hueco_INTERMEDIO`)
- Prioridades **1, 2 y 3** (columnas + filas).
- **Comportamiento:** además de apilar, intenta completar líneas horizontales.
- **Analogía ML:** más features → mejor capacidad de generalización en tableros variados.
### Estrategia 3 — Avanzada (`buscar_hueco_AVANZADO`)
- Prioridades **1, 2, 3, 4 y 5** (columnas + filas + diagonales).
- **Comportamiento:** explota todas las direcciones de combinación.
- **Analogía ML:** modelo con el espacio de features más completo; mayor rendimiento esperado.
En Python, esto está en `columns/ai.py`, clase `ColumnsAI`.
---
## 6. Rotación inteligente (`mover_ia`)
Elegir la columna no basta: la pieza es una **columna de 3 gemas** que se puede rotar. La función `mover_ia` del código C (portada a `_rotate_for_pattern` en Python) ajusta el orden de las gemas según el tipo de patrón detectado:
- **Prioridad 1:** coloca las dos gemas iguales de forma que caigan juntas.
- **Prioridad 2:** alinea la gema coincidente con las dos de abajo.
- **Prioridad 3:** pone en el hueco la gema que completa la fila.
- **Prioridades 4-5:** alinea con la diagonal detectada.
- **Prioridad 6:** separa gemas iguales para evitar bloqueos.
Esto es **razonamiento simbólico**: reglas del tipo "si patrón X, entonces rotar Y".
---
## 7. Mapeo código C → Python
| C (original) | Python (refactor) | Rol |
|---|---|---|
| `tablero[22][10]` | `Board.grid` | Estado del entorno |
| `buscar_hueco_BASICO` | `ColumnsAI._evaluate_columns` (strategy=1) | Clasificador básico |
| `buscar_hueco_INTERMEDIO` | `ColumnsAI._evaluate_columns` (strategy=2) | Clasificador intermedio |
| `buscar_hueco_AVANZADO` | `ColumnsAI._evaluate_columns` (strategy=3) | Clasificador avanzado |
| `mover_ia` | `ColumnsAI._rotate_for_pattern` | Política de rotación |
| `verificar_eliminar` | `Board.find_matches` + `clear_matches` | Detección de recompensa |
| `bajar_bolas` | `Board.apply_gravity` | Dinámica del entorno |
| `machine_learning_menu` | `main.py` + argumentos CLI | Configuración |
---
## 8. ¿Cómo sería un verdadero Machine Learning aquí?
El código original ya anticipaba evoluciones. Estas serían las rutas naturales:
### 8.1 Aprendizaje por refuerzo (Q-Learning / DQN)
- **Estado:** matriz del tablero + pieza actual.
- **Acciones:** 10 columnas × 3 rotaciones = 30 acciones.
- **Recompensa:** +5 por gema eliminada, -100 si game over.
- **Política:** maximizar recompensa acumulada.
La IA heurística actual serviría como **política inicial** (*warm start*) o para generar datos de entrenamiento.
### 8.2 Aprendizaje supervisado
- Registrar partidas de jugadores humanos: `(tablero, pieza) → columna_elegida`.
- Entrenar un clasificador (árbol de decisión, red neuronal) que imite al experto.
- Las 6 prioridades actuales serían las **etiquetas** del dataset.
### 8.3 Feature engineering → ML clásico
Las mismas features que usa el código (gemas adyacentes, colores de la pieza, huecos) pueden alimentar:
- **Random Forest** para predecir puntuación esperada por columna.
- **Regresión logística** para probabilidad de eliminación.
---
## 9. Cómo experimentar con el proyecto Python
```bash
# Instalar dependencias
pip install -r requirements.txt
# Jugar con interfaz gráfica (estrategia avanzada)
python main.py
# Simular 50 movimientos sin ventana (ideal para Colab/Replit)
python main.py --demo --moves 50 --strategy 1
python main.py --demo --moves 50 --strategy 3
# Comparar estrategias con semilla fija
python main.py --demo --moves 100 --strategy 1 --seed 42
python main.py --demo --moves 100 --strategy 3 --seed 42
```
### Controles en modo gráfico
| Tecla | Acción |
|---|---|
| Espacio | Ejecutar un turno de la IA |
| A | Auto-juego continuo |
| 1 / 2 / 3 | Cambiar estrategia básica / intermedia / avanzada |
| M | Alternar modo manual |
| R | Reiniciar partida |
| ← → ↑ ↓ | Mover/rotar/soltar (modo manual) |
Los **círculos de colores bajo el tablero** muestran la prioridad que la IA asignó a cada columna en el turno actual — una visualización directa del "clasificador".
---
## 10. Conclusión pedagógica
Este proyecto es un excelente ejemplo de que **"Inteligencia Artificial" no siempre significa redes neuronales**. La IA de Columns es un **agente basado en conocimiento**:
- Conoce las **reglas del juego** (qué combinaciones eliminan gemas).
- Conoce **patrones útiles** (codificados como prioridades).
- **Actúa** eligiendo la mejor acción según esas reglas.
Es el mismo pipeline conceptual del ML — *observar → extraer features → clasificar → actuar* — pero con reglas escritas por humanos en lugar de pesos aprendidos por datos.
Eso no lo hace menos valioso: de hecho, muchos sistemas industriales siguen usando reglas expertas cuando los datos son escasos o se necesita explicabilidad. Este proyecto demuestra ese enfoque en un entorno lúdico y visual.
---
## Referencias del código
- Original C: `AIColumnsGame_HelperFunctions.C` (tres estrategias completas)
- Original C: `AIColumns_Machine-Learning.C` (versión con menú extendido)
- Port Python: `columns/ai.py`, `columns/board.py`, `columns/game.py`