diff --git a/azar.c b/azar.c
new file mode 100644
index 0000000..fd47323
--- /dev/null
+++ b/azar.c
@@ -0,0 +1,27 @@
+// Este fichero se le da al alumno
+#include <time.h>	// time()
+#include <stdlib.h>	// rand(), srand()
+#include <stdio.h>	// printf()
+#include "azar.h"
+
+/*
+ * inicializar_azar() se tiene que ejecutar una vez al principio del main
+ * para inicializar la generación de números aleatorios
+ */
+//void inicializar_azar() {
+	/*
+	 * Para que la sequencia de numeros aleatorios sea igual en cada
+	 * ejecucion usad el srand (0) en lugar del srand(time).
+	 */
+	//srand(0);
+//	srand( (unsigned)time( NULL ) );
+//}
+
+/*
+ * numero_al_azar(max) devuelve un número entero al azar entre 0 y max-1
+ */
+int numero_al_azar(int max) {
+	srand(time(NULL));
+	return ( rand() % max); 
+}
+
diff --git a/azar.h b/azar.h
new file mode 100644
index 0000000..b535198
--- /dev/null
+++ b/azar.h
@@ -0,0 +1,9 @@
+// Este fichero se le da al alumno
+#ifndef AZAR_H 
+#define	AZAR_H
+
+void inicializar_azar();
+int numero_al_azar(int max);
+
+#endif	/* AZAR_H */
+
diff --git a/duerme.c b/duerme.c
new file mode 100644
index 0000000..9347255
--- /dev/null
+++ b/duerme.c
@@ -0,0 +1,47 @@
+// Este fichero se le da al alumno
+#include <time.h>
+#include "duerme.h"
+
+#define UN_RATO_SEGUNDOS	1		// 1 segundo
+#define UN_RATO_NANOSEGUNDOS	500000000	// 0.5 segundos
+
+/*
+ * Hace que la ejecucion del programa se detenga durante
+ * el numero de segundos que se le pasa por parametro
+ */
+void duerme_n_segundos(long segundos) {
+	struct timespec tim, tim2;
+	tim.tv_sec = segundos;
+	tim.tv_nsec = 0;
+
+	nanosleep(&tim , &tim2);
+}
+
+/*
+ * Hace que la ejecucion del programa se detenga durante
+ * el numero de nanosegundos que se le pasa por parametro
+ */
+void duerme_n_nanosegundos(long nanosegundos) {
+	struct timespec tim, tim2;
+	tim.tv_sec = 0;
+	tim.tv_nsec = nanosegundos;
+
+	nanosleep(&tim , &tim2);
+}
+
+/*
+ * Hace que la ejecucion del programa se detenga durante
+ * un numero de segundos predeterminado
+ */
+void duerme_un_rato() {
+	duerme_n_segundos(UN_RATO_SEGUNDOS);
+}
+
+/*
+ * Hace que la ejecucion del programa se detenga durante
+ * un numero de nanosegundos predeterminado
+ */
+void duerme_un_nano_rato() {
+	duerme_n_nanosegundos(UN_RATO_NANOSEGUNDOS);
+}
+
diff --git a/duerme.h b/duerme.h
new file mode 100644
index 0000000..c3024d0
--- /dev/null
+++ b/duerme.h
@@ -0,0 +1,11 @@
+// Este fichero se le da al alumno
+#ifndef DUERME_H
+#define	DUERME_H
+
+void duerme_n_segundos(long segundos);
+void duerme_n_nanosegundos(long nanosegundos);
+void duerme_un_rato();
+void duerme_un_nano_rato();
+
+#endif	/* DUERME_H */
+
diff --git a/ficha.c b/ficha.c
new file mode 100644
index 0000000..4998af2
--- /dev/null
+++ b/ficha.c
@@ -0,0 +1,37 @@
+#include <stdio.h>  
+typedef struct{
+    int num1, num2;
+}t_ficha;
+
+void inicializar_ficha (t_ficha *ficha, int i, int j);
+void imprimir_ficha (t_ficha f, int visible);
+void girar_ficha (t_ficha *ficha);
+int doble();
+
+void imprimir_ficha(t_ficha ficha, int visible){
+	
+	printf("%d:%d|", ficha.num1, ficha.num2);
+}
+
+void girar_ficha(t_ficha *ficha){    // num1 es canvia per num2 i al contrari
+	int aux, i;
+   
+    aux=ficha->num1;
+    ficha->num1=ficha->num2;
+    ficha->num2=aux;
+
+}
+
+int doble()
+{	t_ficha ficha[28];
+	int i;
+	
+	if(ficha[i].num1==ficha[i].num2) //Si es un doble num1=num2
+		return(1);
+	else return(0);
+}
+
+void inicializar_ficha (t_ficha *ficha, int i, int j) {      
+            ficha->num2=j; 
+            ficha->num1=i;
+        }
diff --git a/ficha.h b/ficha.h
new file mode 100644
index 0000000..f2cf234
--- /dev/null
+++ b/ficha.h
@@ -0,0 +1,18 @@
+#ifndef FICHA_H
+#define FICHA_H
+
+#define FALSE	0
+#define TRUE	1
+
+#define NUM_FICHAS_DOMINO		28
+
+typedef struct{
+    int num1, num2;
+}t_ficha;
+
+void inicializar_ficha(t_ficha *p_f, int a, int b);
+void girar_ficha(t_ficha *p_f);
+void imprimir_ficha(t_ficha f, int visible);
+
+#endif // FICHA_H
+
diff --git a/jugador.c b/jugador.c
new file mode 100644
index 0000000..ad04bc7
--- /dev/null
+++ b/jugador.c
@@ -0,0 +1,112 @@
+#include "ficha.h"
+#include <stdio.h>
+
+#define MIN_JUGADORES 2
+#define MAX_JUGADORES 4
+
+#define T_HUMANO 1
+#define T_ROBOT 2
+
+#define TRUE 1
+#define FALSE 0
+
+typedef struct
+{
+	int n_fichas;
+	t_ficha f[NUM_FICHAS_DOMINO]; // Fichas que tiene
+	int tipo;
+	int peso;
+} t_jugador;
+
+typedef struct
+{
+	int n_jugadores;
+	int un_humano; // TRUE or FALSE
+	int turno;
+	t_jugador j[MAX_JUGADORES]; // Fichas que tiene y otras cosas
+} t_jugadores;
+
+void imprimir_jugador(t_jugador j, int visible);
+void imprimir_jugadores(t_jugadores js, int visible);
+void que_jugador_tiene_doble_mas_alto(t_jugadores js, int *p_nj, int *p_nf);
+void pasar_turno(t_jugadores *p_js);
+void imprimir_turno(t_jugadores _js);
+
+void imprimir_jugador(t_jugador j, int visible)
+{
+	int i;
+	t_ficha f;
+
+	if (j.tipo == T_ROBOT)
+	{ // Robot
+		if (visible == FALSE)
+		{ // Omnisciencia apagada
+			for (i = 0; i < j.n_fichas; i++)
+			{
+				printf("?:?|");
+			}
+		}
+		else
+		{ // Omnisciencia encendida
+			for (i = 0; i < j.n_fichas; i++)
+			{
+				printf("%d:%d|", j.f[i].num1, j.f[i].num2);
+			}
+		}
+	}
+	else
+	{ // Humano
+		for (i = 0; i < j.n_fichas; i++)
+		{
+			printf("%d:%d|", j.f[i].num1, j.f[i].num2);
+		}
+	}
+}
+void imprimir_jugadores(t_jugadores js, int visible)
+{
+	int i;
+	for (i = 0; i < js.n_jugadores; i++)
+	{ //Ejecuta el codigo para cada jugador
+		printf("J%d 	", i);
+		imprimir_jugador(js.j[i], visible);
+		if (js.j[i].tipo == T_ROBOT)
+		{ //Robot
+			printf("Robot\n");
+		}
+		else
+		{ //Humano
+			printf("Humano\n");
+		}
+	}
+}
+void que_jugador_tiene_doble_mas_alto(t_jugadores js, int *p_nj, int *p_nf)
+{
+	int i, j, max = 0, encontrado = 0;
+
+	for (i = 0; i < js.n_jugadores; i++)
+	{ //Comprueba que jugador tiene el doble mas alto
+		for (j = 0; j < js.j[i].n_fichas; j++)
+		{
+			if (js.j[i].f[j].num1 == js.j[i].f[j].num2 && js.j[i].f[j].num1 > max)
+			{
+				max = js.j[i].f[j].num1;
+				*p_nj = i;
+				*p_nf = j;
+				encontrado = 1;
+			}
+		}
+	}
+	if (encontrado == 0)
+	{
+		*p_nj = 0;
+		*p_nf = 0;
+	}
+}
+void pasar_turno(t_jugadores *p_js)
+{
+	p_js->turno = ((p_js->turno) + 1) % (p_js->n_jugadores); // Suma 1 al turno a menos que sea máximo, entonces vuelve al inicial (0)
+}
+void imprimir_turno(t_jugadores js)
+{
+	printf("Turno: %d\n", js.turno);
+}
diff --git a/jugador.h b/jugador.h
new file mode 100644
index 0000000..78766ee
--- /dev/null
+++ b/jugador.h
@@ -0,0 +1,33 @@
+#ifndef JUGADOR_H
+#define JUGADOR_H
+
+#include "ficha.h"
+
+#define MIN_JUGADORES	2
+#define MAX_JUGADORES	4
+
+#define T_HUMANO	1
+#define T_ROBOT		2
+
+typedef struct {
+	int	n_fichas;
+	t_ficha	f[NUM_FICHAS_DOMINO];	// Fichas que tiene
+	int	tipo;
+    int peso;
+} t_jugador;
+
+typedef struct {
+	int n_jugadores;
+	int un_humano;	// TRUE or FALSE
+	int turno;
+	t_jugador	j[MAX_JUGADORES]; // Fichas que tiene y otras cosas
+} t_jugadores;
+
+void imprimir_jugador(t_jugador j, int visible);
+void imprimir_jugadores(t_jugadores js, int visible);
+void que_jugador_tiene_doble_mas_alto(t_jugadores js, int *p_nj, int *p_nf);
+void pasar_turno(t_jugadores *p_js);
+void imprimir_turno(t_jugadores _js);
+
+#endif // JUGADOR_H
+
diff --git a/main b/main
new file mode 100644
index 0000000..9bef283
Binary files /dev/null and b/main differ
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..e0c3a22
--- /dev/null
+++ b/main.c
@@ -0,0 +1,21 @@
+#include "partida.h"
+//incloure totes les llibreries
+
+#define TRUE 1
+#define FALSE 0
+
+int main(){
+	int acabado;
+	t_partida partida;
+	inicializar_partida(&partida);
+	realizar_jugada(&partida);
+	acabado=FALSE;            // Inicialitzem "acabado" a 0 perque la partida comença i ha d'entrar al while
+	while(acabado==FALSE)     // Entra sempre que es pugui seguint jugar
+	{	
+                imprimir_estado_partida(partida);
+		realizar_jugada(&partida);
+		acabado=se_ha_acabado_la_partida(partida);
+	}
+	
+	imprimir_estado_final_partida(partida);   // Printf de la partida en la jugada final
+}
diff --git a/mesa.c b/mesa.c
new file mode 100644
index 0000000..51e21c9
--- /dev/null
+++ b/mesa.c
@@ -0,0 +1,98 @@
+#include <stdio.h>
+#include "ficha.h"
+#define NUM_FICHAS_DOMINO 28
+
+typedef struct
+{
+	int n_fichas;
+	t_ficha f[NUM_FICHAS_DOMINO];
+} t_mesa;
+
+void inicializar_mesa(t_mesa *p_m)
+{
+	p_m->n_fichas = 0; // Inicialmente no hay fichas en la mesa
+}
+
+void imprimir_mesa(t_mesa m, int dim)
+{
+	int i, pos2;
+
+	printf("\nMesa:   ");
+	if (dim == FALSE)
+	{ //sense 2d
+		for (i = 0; i < m.n_fichas; i++)
+			printf("%d:%d|", m.f[i].num1, m.f[i].num2);
+	}
+	else
+	{ //con 2d
+		printf("\n");
+
+		for (i = 0; i < m.n_fichas; i++)
+		{
+			if (m.f[i].num1 == m.f[i].num2)
+			{ //es doble, poner vertical
+				printf("%d|", m.f[i].num1);
+			}
+			else
+			{
+				printf("___ ");
+			}
+		}
+		printf("\n");
+		for (i = 0; i < m.n_fichas; i++)
+		{
+			if (m.f[i].num1 == m.f[i].num2)
+			{ //es doble, poner vertical
+				printf("-|");
+			}
+			else
+			{
+				printf("%d:%d|", m.f[i].num1, m.f[i].num2); //es normal, se imprime normal
+			}
+		}
+		printf("\n");
+		for (i = 0; i < m.n_fichas; i++)
+		{
+			if (m.f[i].num1 == m.f[i].num2)
+			{ //es doble, poner vertical
+				printf("%d|", m.f[i].num1);
+			}
+			else
+			{
+				printf("    ");
+			}
+		}
+		printf("\n");
+	}
+}
+
+void pon_en_mesa_por_la_derecha(t_mesa *p_m, t_ficha f)
+{
+	int i;
+
+	p_m->f[p_m->n_fichas] = f; // Posición de la derecha: n_fichas porque es la primera posición vacia en el vector
+	p_m->n_fichas++;
+}
+void pon_en_mesa_por_la_izquierda(t_mesa *p_m, t_ficha f)
+{
+	int i;
+	p_m->n_fichas++;
+	for (i = p_m->n_fichas; i > 0; i--)
+	{ // Desplaza toda la mesa un lugar a la derecha
+		p_m->f[i] = p_m->f[i - 1];
+	}
+	p_m->f[0] = f; // Introduce en la posición 0 la nueva ficha
+}
+
+int extremo_izquierdo_mesa(t_mesa m)
+{
+	int izquierdo;
+	izquierdo = m.f[0].num1;
+	return (izquierdo);
+}
+int extremo_derecho_mesa(t_mesa m)
+{
+	int derecho;
+	derecho = m.f[m.n_fichas - 1].num2;
+	return (derecho);
+}
diff --git a/mesa.h b/mesa.h
new file mode 100644
index 0000000..6fc068e
--- /dev/null
+++ b/mesa.h
@@ -0,0 +1,20 @@
+#ifndef MESA_H
+#define MESA_H
+
+#include "ficha.h"
+
+typedef struct {
+	int n_fichas;
+	t_ficha	f[NUM_FICHAS_DOMINO];
+} t_mesa;
+
+void inicializar_mesa(t_mesa *p_m);
+void imprimir_mesa(t_mesa m, int dim);
+
+void pon_en_mesa_por_la_derecha(t_mesa *p_m, t_ficha f);
+void pon_en_mesa_por_la_izquierda(t_mesa *p_m, t_ficha f);
+
+int extremo_izquierdo_mesa(t_mesa m);
+int extremo_derecho_mesa(t_mesa m);
+
+#endif // MESA_H
diff --git a/partida.c b/partida.c
new file mode 100644
index 0000000..693a7e1
--- /dev/null
+++ b/partida.c
@@ -0,0 +1,327 @@
+#include <stdio.h>
+#include <string.h>
+#include "jugador.h"
+#include "mesa.h"
+#include "pila.h"
+#include "tirada.h"
+#include "preguntas.h"
+#include "duerme.h"
+#include "azar.h"
+
+#define TRUE 1
+#define FALSE 0
+typedef struct
+{
+    t_jugadores js;
+    t_mesa m;    // Fichas jugadas
+    t_pila pi;   // Fichas no jugadas y que no tiene nadie
+    int visible; // Pila y fichas de robots visibles
+    int dim;     // Ver mesa en 2D (versus 1D)
+    // visible y mesa_2d pueden valer TRUE o FALSE
+    int pasadas; // Veces consecutivas que un jugador pasa
+    // si pasadas == n_jugadores se acaba el juego.
+} t_partida;
+
+void inicializar_partida(t_partida *p_pa);
+void imprimir_estado_partida(t_partida pa);
+void realizar_jugada(t_partida *p_pa);
+int se_ha_acabado_la_partida(t_partida pa);
+
+void inicializar_partida(t_partida *p_pa)
+{
+    int i, j, p, k, nj, nf;
+    char s1[50] = "¿Numero de jugadores?", s2[50] = "¿Un jugador humano?", s3[50] = "¿Quieres omnisciencia?", s4[50] = "¿Quieres ver la mesa en 2D?";
+
+    p_pa->pasadas = 0;
+
+    p_pa->js.n_jugadores = preguntar_n_en_rango(&s1[0], 2, 4); //Realizamos las preguntas
+    p_pa->js.un_humano = preguntar_si_o_no(&s2[0]);
+    p_pa->visible = preguntar_si_o_no(&s3[0]);
+    p_pa->dim = preguntar_si_o_no(&s4[0]);
+    printf("\n");
+
+    inicializar_pila(&(p_pa->pi));
+
+    for (i = 0; i < p_pa->js.n_jugadores; i++) //Repartir fichas aleatoriamente
+        for (j = 0; j < 7; j++)
+            p_pa->js.j[i].f[j] = coger_ficha_de_la_pila(&(p_pa->pi));
+
+    if (p_pa->js.un_humano == TRUE)
+    { // Inicializamos los jugadores
+        p_pa->js.j[0].tipo = T_HUMANO;
+        p_pa->js.j[0].n_fichas = 7;
+        for (i = 1; i < p_pa->js.n_jugadores; i++)
+        {
+            p_pa->js.j[i].tipo = T_ROBOT;
+            p_pa->js.j[i].n_fichas = 7;
+        }
+    }
+    else
+    {
+        for (i = 0; i < p_pa->js.n_jugadores; i++)
+        {
+            p_pa->js.j[i].tipo = T_ROBOT;
+            p_pa->js.j[i].n_fichas = 7;
+        }
+    }
+    que_jugador_tiene_doble_mas_alto(p_pa->js, &nj, &nf); // Que jugador empieza la partida
+
+    inicializar_mesa(&(p_pa->m));
+    imprimir_pila(p_pa->pi, p_pa->visible);
+
+    pon_en_mesa_por_la_izquierda(&(p_pa->m), p_pa->js.j[nj].f[nf]);
+    imprimir_mesa(p_pa->m, p_pa->dim);
+    printf("\n");
+
+    for (i = nf; i < p_pa->js.j[nj].n_fichas; i++)
+        p_pa->js.j[nj].f[i] = p_pa->js.j[nj].f[i + 1];
+    p_pa->js.j[nj].n_fichas--;
+
+    p_pa->js.turno = nj;
+    imprimir_jugadores(p_pa->js, p_pa->visible);
+    pasar_turno(&(p_pa->js));
+    imprimir_turno(p_pa->js);
+}
+
+void imprimir_estado_partida(t_partida pa)
+{
+    int i;
+    imprimir_pila(pa.pi, pa.visible);
+    //POSAR MESA EN NEGRETA
+    imprimir_mesa(pa.m, pa.dim);
+    printf("\n");
+    imprimir_jugadores(pa.js, pa.visible);
+    imprimir_turno(pa.js);
+}
+void imprimir_estado_final_partida(t_partida pa)
+{ // Printf de la partida en el momento del final de la partida
+    int i;
+    duerme_un_rato(10);
+    printf("\tESTADO FINAL DE PARTIDA:\n\n");
+    pa.visible = TRUE;
+
+    imprimir_pila(pa.pi, pa.visible);
+    //POSAR MESA EN NEGRETA
+    imprimir_mesa(pa.m, pa.dim);
+    printf("\n");
+    imprimir_jugadores(pa.js, pa.visible);
+    printf("\n");
+}
+
+void realizar_jugada(t_partida *p_pa)
+{
+    int tirada = -1, i, v;
+    t_tiradas ts;
+
+    ts = calcular_tiradas_posibles(p_pa->js.j[p_pa->js.turno], p_pa->m); //Calculamos si hay tiradas posibles
+
+    while (ts.n_tiradas == 0 && p_pa->pi.n_fichas != 0)
+    { // Si no puede tirar tiene que robar ficha
+        p_pa->js.j[p_pa->js.turno].f[p_pa->js.j[p_pa->js.turno].n_fichas] = coger_ficha_de_la_pila(&(p_pa->pi));
+
+        if (p_pa->visible == TRUE)
+        {                                                    // Omnisciencia activada
+            if (p_pa->js.j[p_pa->js.turno].tipo == T_HUMANO) // Si es humano muestra la ficha
+                printf("Vas a la pila! Pillas un %d:%d ;P\n", p_pa->js.j[p_pa->js.turno].f[p_pa->js.j[p_pa->js.turno].n_fichas].num1, p_pa->js.j[p_pa->js.turno].f[p_pa->js.j[p_pa->js.turno].n_fichas].num2);
+            else
+                printf("Va a la pila! Pilla un %d:%d ;)\n", p_pa->js.j[p_pa->js.turno].f[p_pa->js.j[p_pa->js.turno].n_fichas].num1, p_pa->js.j[p_pa->js.turno].f[p_pa->js.j[p_pa->js.turno].n_fichas].num2); // Si es robot muestra la ficha
+            p_pa->js.j[p_pa->js.turno].n_fichas++;
+            ts = calcular_tiradas_posibles(p_pa->js.j[p_pa->js.turno], p_pa->m);
+        }
+        if (p_pa->visible == FALSE)
+        {
+            if (p_pa->js.j[p_pa->js.turno].tipo == T_HUMANO) //Si es humano muestra la ficha
+                printf("Vas a la pila! Pillas un %d:%d ;P\n", p_pa->js.j[p_pa->js.turno].f[p_pa->js.j[p_pa->js.turno].n_fichas].num1, p_pa->js.j[p_pa->js.turno].f[p_pa->js.j[p_pa->js.turno].n_fichas].num2);
+            else
+                printf("Va a la pila! ;)\n"); //Si es robot no muestra la ficha
+            p_pa->js.j[p_pa->js.turno].n_fichas++;
+            ts = calcular_tiradas_posibles(p_pa->js.j[p_pa->js.turno], p_pa->m);
+        }
+    }
+
+    imprimir_tiradas(ts, p_pa->js.j[p_pa->js.turno]);
+
+    if (p_pa->js.j[p_pa->js.turno].tipo == T_HUMANO)
+    { //tira humano
+        if (ts.n_tiradas == 0 && p_pa->pi.n_fichas == 0)
+        { //HUMANO no puede tirar y pasa turno
+            printf("Pasas! :(\n\n");
+            p_pa->pasadas++;
+        }
+
+        if (ts.n_tiradas > 0)
+        {
+            p_pa->pasadas = 0;
+            if (ts.cont_dobles > 1)
+                v = ts.n_tiradas; //Si se dobledobla cuenta esa tirada como extra
+            else
+                v = ts.n_tiradas - 1;
+            printf("¿Que tirada juegas[0-%d]?: ", v);
+            scanf("%d", &tirada);
+            while (tirada < 0 || tirada > v)
+            {
+                printf("¡%d no es una opcion!\n", tirada);
+                printf("¿Que tirada juegas[0-%d]?: ", v);
+                scanf("%d", &tirada);
+            }
+            printf("\n");
+            if ((ts.cont_dobles > 1) && (tirada == ts.n_tiradas))
+            {                                                                                                          //Se dobledobla cuando el contador tiene 2 tiradas con dobles y el jugador la escoje
+                pon_en_mesa_por_la_derecha(&(p_pa->m), p_pa->js.j[p_pa->js.turno].f[ts.t[ts.dobleizquierda].n_ficha]); //Doble por la derecha
+                pon_en_mesa_por_la_izquierda(&(p_pa->m), p_pa->js.j[p_pa->js.turno].f[ts.t[ts.doblederecha].n_ficha]); //Doble por la izquierda
+                for (i = ts.t[ts.doblederecha].n_ficha; i < p_pa->js.j[p_pa->js.turno].n_fichas - 1; i++)              // Eliminar un doble del vector de fichas del jugador
+                    p_pa->js.j[p_pa->js.turno].f[i] = p_pa->js.j[p_pa->js.turno].f[i + 1];
+                p_pa->js.j[p_pa->js.turno].n_fichas--;
+                if (ts.t[ts.dobleizquierda].n_ficha > ts.t[ts.doblederecha].n_ficha)
+                { // Eliminar el otro doble del vector de fichas dependiendo de donde se encuentre respecto al primer doble
+                    for (i = ts.t[ts.dobleizquierda - 1].n_ficha; i < p_pa->js.j[p_pa->js.turno].n_fichas - 1; i++)
+                        p_pa->js.j[p_pa->js.turno].f[i] = p_pa->js.j[p_pa->js.turno].f[i + 1];
+                    p_pa->js.j[p_pa->js.turno].n_fichas--;
+                }
+                else
+                {
+                    for (i = ts.t[ts.dobleizquierda - 1].n_ficha; i < p_pa->js.j[p_pa->js.turno].n_fichas - 1; i++)
+                        p_pa->js.j[p_pa->js.turno].f[i] = p_pa->js.j[p_pa->js.turno].f[i + 1];
+                    p_pa->js.j[p_pa->js.turno].n_fichas--;
+                }
+            }
+            if (tirada != ts.n_tiradas)
+            {                                    //Si no se dobledobla
+                if (ts.t[tirada].girada == TRUE) //Gira la ficha si debe hacerlo
+                    girar_ficha(&(p_pa->js.j[p_pa->js.turno].f[ts.t[tirada].n_ficha]));
+                if (ts.t[tirada].extremo == 'd')
+                {
+                    pon_en_mesa_por_la_derecha(&(p_pa->m), p_pa->js.j[p_pa->js.turno].f[ts.t[tirada].n_ficha]); //Coloca por la derecha
+                }
+                else
+                {
+                    pon_en_mesa_por_la_izquierda(&(p_pa->m), p_pa->js.j[p_pa->js.turno].f[ts.t[tirada].n_ficha]); //Coloca por la izquierda
+                }
+                for (i = ts.t[tirada].n_ficha; i < p_pa->js.j[p_pa->js.turno].n_fichas - 1; i++)
+                    p_pa->js.j[p_pa->js.turno].f[i] = p_pa->js.j[p_pa->js.turno].f[i + 1];
+                p_pa->js.j[p_pa->js.turno].n_fichas--;
+            }
+        }
+    }
+    else
+    { /*TIRA UN ROBOT*/
+        if (ts.n_tiradas == 0 && p_pa->pi.n_fichas == 0)
+        {
+            printf("Pasa! :)\n\n"); //Si no puede tirar pasa turno
+            p_pa->pasadas++;
+        }
+        //Robot no puede tirar y pasa turno
+
+        if (ts.n_tiradas > 0)
+        {
+            p_pa->pasadas = 0;
+            if (ts.cont_dobles > 1)
+                ts.n_tiradas++;                    // Dobledoblarse cuenta como una tirada más
+            tirada = numero_al_azar(ts.n_tiradas); // Escoge una tirada al azar
+            if ((ts.cont_dobles > 1) && (tirada == ts.n_tiradas))
+            {                                                                                                          //Se dobledobla cuando el contador tiene 2 tiradas con dobles y el jugador la escoje
+                pon_en_mesa_por_la_derecha(&(p_pa->m), p_pa->js.j[p_pa->js.turno].f[ts.t[ts.dobleizquierda].n_ficha]); // Doble por la derecha
+                pon_en_mesa_por_la_izquierda(&(p_pa->m), p_pa->js.j[p_pa->js.turno].f[ts.t[ts.doblederecha].n_ficha]); // Doble por la izquierda
+                for (i = ts.t[ts.doblederecha].n_ficha; i < p_pa->js.j[p_pa->js.turno].n_fichas - 1; i++)              // Eliminar un doble del vector de fichas del robot
+                    p_pa->js.j[p_pa->js.turno].f[i] = p_pa->js.j[p_pa->js.turno].f[i + 1];
+                p_pa->js.j[p_pa->js.turno].n_fichas--;
+                if (ts.t[ts.dobleizquierda].n_ficha > ts.t[ts.doblederecha].n_ficha)
+                { //Eliminar el otro doble dependiendo de su posición respecto al primero
+                    for (i = ts.t[ts.dobleizquierda - 1].n_ficha; i < p_pa->js.j[p_pa->js.turno].n_fichas - 1; i++)
+                        p_pa->js.j[p_pa->js.turno].f[i] = p_pa->js.j[p_pa->js.turno].f[i + 1];
+                    p_pa->js.j[p_pa->js.turno].n_fichas--;
+                }
+                else
+                {
+                    for (i = ts.t[ts.dobleizquierda - 1].n_ficha; i < p_pa->js.j[p_pa->js.turno].n_fichas - 1; i++)
+                        p_pa->js.j[p_pa->js.turno].f[i] = p_pa->js.j[p_pa->js.turno].f[i + 1];
+                    p_pa->js.j[p_pa->js.turno].n_fichas--;
+                }
+            }
+            else
+            {
+                if (ts.t[tirada].girada == TRUE) //Gira la ficha si debe hacerlo
+                    girar_ficha(&(p_pa->js.j[p_pa->js.turno].f[ts.t[tirada].n_ficha]));
+                imprimir_tirada(ts.t[tirada], p_pa->js.j[p_pa->js.turno]);
+                if (ts.t[tirada].extremo == 'd')
+                {
+                    pon_en_mesa_por_la_derecha(&(p_pa->m), p_pa->js.j[p_pa->js.turno].f[ts.t[tirada].n_ficha]); //Coloca por la derecha
+                }
+                else
+                {
+                    pon_en_mesa_por_la_izquierda(&(p_pa->m), p_pa->js.j[p_pa->js.turno].f[ts.t[tirada].n_ficha]); //Coloca por la izquierda
+                }
+                for (i = ts.t[tirada].n_ficha; i < p_pa->js.j[p_pa->js.turno].n_fichas - 1; i++) //Elimina la ficha del vector
+                    p_pa->js.j[p_pa->js.turno].f[i] = p_pa->js.j[p_pa->js.turno].f[i + 1];
+                p_pa->js.j[p_pa->js.turno].n_fichas--;
+            }
+            duerme_un_rato(4);
+        }
+    }
+
+    pasar_turno(&(p_pa->js));
+}
+
+int se_ha_acabado_la_partida(t_partida pa)
+{
+    int aux = FALSE, minpeso = 200, i, j, jugminpeso, empate = FALSE;
+
+    if (pa.js.turno > 0) // Como se_ha_acabado_la_partida se coloca despues de pasar_turno, pa.js.turno debe ser un numero menos
+        pa.js.turno = pa.js.turno - 1;
+
+    else // NO puede ser -1, asi que vuelve a n_jugadores-1 (maximo)
+        pa.js.turno = pa.js.n_jugadores - 1;
+
+    if (pa.js.j[pa.js.turno].n_fichas == 0)
+    { // Condición de ganador
+        if (pa.js.j[pa.js.turno].tipo == T_HUMANO)
+        { // Gana el humano
+            printf("===>>> HAS GANADO! :) <<<===\n\n");
+        }
+        else
+        { //Gana el robot
+            printf("===>>> HA GANADO EL J%d! :/ <<<===\n\n", pa.js.turno);
+        }
+        aux = TRUE;
+        return (aux);
+    }
+    else if (pa.pasadas >= pa.js.n_jugadores)
+    { //Ganador en bloqueo
+        printf("===>>> JUEGO BLOQUEADO <<<===\n\n");
+        aux = TRUE;
+        for (i = 0; i < pa.js.n_jugadores; i++)
+        { // Calcula el peso de las fichas
+            pa.js.j[i].peso = 0;
+            for (j = 0; j < pa.js.j[i].n_fichas; j++)
+            {
+                pa.js.j[i].peso = pa.js.j[i].peso + pa.js.j[i].f[j].num1 + pa.js.j[i].f[j].num2;
+            }
+            printf("Peso J%d=%d\n", i, pa.js.j[i].peso);
+        }
+        for (i = 0; i < pa.js.n_jugadores; i++)
+        { //Peso minimo con su jugador
+            if (minpeso > pa.js.j[i].peso)
+            {
+                minpeso = pa.js.j[i].peso;
+                jugminpeso = i;
+            }
+        }
+        for (i = 0; i < pa.js.n_jugadores; i++)
+        { // Caso de empate (tablas)
+            if (minpeso == pa.js.j[i].peso && i != jugminpeso)
+            {
+                empate = TRUE;
+            }
+        }
+        if (empate == TRUE)
+        { // Tablas
+            printf("\n===>>> TABLAS ENTRE J%d Y J%d CON MINIMO PESO(%d de peso) <<<===\n\n\n", jugminpeso, i, minpeso);
+        }
+        else
+        { // Ganador
+            printf("\n===>>> HA GANADO EL J%d POR MINIMO PESO(%d de peso) <<<===\n\n\n", jugminpeso, minpeso);
+        }
+    }
+    else
+        return (aux);
+}
diff --git a/partida.h b/partida.h
new file mode 100644
index 0000000..e58e5f5
--- /dev/null
+++ b/partida.h
@@ -0,0 +1,27 @@
+#ifndef PARTIDA_H
+#define PARTIDA_H
+
+#include "jugador.h"
+#include "mesa.h"
+#include "pila.h"
+#include "tirada.h"
+
+typedef struct
+{
+	t_jugadores js;
+	t_mesa m;	 // Fichas jugadas
+	t_pila pi;	 // Fichas no jugadas y que no tiene nadie
+	int visible; // Pila y fichas de robots visibles
+	int mesa_2d; // Ver mesa en 2D (versus 1D)
+				 // visible y mesa_2d pueden valer TRUE o FALSE
+	int pasadas; // Veces consecutivas que un jugador pasa
+				 // si pasadas == n_jugadores se acaba el juego.
+} t_partida;
+
+void inicializar_partida(t_partida *p_pa);
+void imprimir_estado_partida(t_partida pa);
+void imprimir_estado_final_partida(t_partida pa);
+void realizar_jugada(t_partida *p_pa);
+int se_ha_acabado_la_partida(t_partida pa);
+
+#endif // PARTIDA_H
diff --git a/pila.c b/pila.c
new file mode 100644
index 0000000..77aa00d
--- /dev/null
+++ b/pila.c
@@ -0,0 +1,74 @@
+#include <stdio.h>
+#include "azar.h"
+#include "ficha.h"
+#define NUM_FICHAS_DOMINO 28
+#define FALSE 0
+#define TRUE 1
+
+typedef struct
+{
+	int n_fichas;
+	t_ficha f[NUM_FICHAS_DOMINO];
+} t_pila;
+
+void imprimir_pila(t_pila pi, int visible);
+void inicializar_pila(t_pila *pi);
+int esta_la_pila_vacia(t_pila pi);
+t_ficha coger_ficha_de_la_pila(t_pila *pi);
+
+void inicializar_pila(t_pila *pi)
+{
+	int i = 0, j, k;
+
+	pi->n_fichas = NUM_FICHAS_DOMINO; // Al inicio todas las fichas estan en la pila
+	for (j = 0; j < 7; j++)
+		for (k = j; k < 7; k++)
+		{
+			inicializar_ficha(&pi->f[i], j, k); //Inicializa las 28 fichas
+			i++;
+		}
+}
+
+void imprimir_pila(t_pila pi, int visible)
+{
+	int i;
+
+	if (visible == TRUE)
+	{ // Omnisciencia activada
+		printf("Pila:\t");
+		for (i = 0; i < pi.n_fichas; i++)
+			imprimir_ficha(pi.f[i], visible);
+	}
+
+	else
+	{ // Omnisciencia apagada
+		printf("Pila:\t");
+		for (i = 0; i < pi.n_fichas; i++)
+			printf("?:?|");
+	}
+	if (pi.n_fichas == 0)
+		printf("La pila esta vacia");
+}
+
+int esta_la_pila_vacia(t_pila pi)
+{
+	if (pi.n_fichas == 0)
+		return (TRUE);
+
+	else
+		return (FALSE);
+}
+
+t_ficha coger_ficha_de_la_pila(t_pila *pi)
+{
+	int i, pos;
+	t_pila aux;
+	pos = numero_al_azar(pi->n_fichas); // Escoge una ficha aleatoria
+	aux.f[pos] = pi->f[pos];			// Guarda esta ficha aleatoria en un auxiliar
+	for (i = pos; i < (pi->n_fichas - 1); i++)
+	{ // Elimina la ficha robada del vector de la pila
+		pi->f[i] = pi->f[i + 1];
+	}
+	pi->n_fichas--;
+	return (aux.f[pos]); // El return devuelve la ficha robada
+}
diff --git a/pila.h b/pila.h
new file mode 100644
index 0000000..1b15937
--- /dev/null
+++ b/pila.h
@@ -0,0 +1,17 @@
+#ifndef PILA_H
+#define PILA_H
+
+#include "ficha.h"
+
+typedef struct
+{
+	int n_fichas;
+	t_ficha f[NUM_FICHAS_DOMINO];
+} t_pila;
+
+void inicializar_pila(t_pila *pi);
+void imprimir_pila(t_pila pi, int visible);
+t_ficha coger_ficha_de_la_pila(t_pila *pi);
+int esta_la_pila_vacia(t_pila pi);
+
+#endif // PILA_H
diff --git a/preguntas.c b/preguntas.c
new file mode 100644
index 0000000..a5911f8
--- /dev/null
+++ b/preguntas.c
@@ -0,0 +1,42 @@
+// Este fichero se le da al alumno
+#include <stdio.h>
+
+int fuera_de_rango(int n, int min, int max)
+{
+	return ((n < min) || (n > max));
+}
+
+void convertir_a_minusculas(char *c)
+{
+	if ((*c >= 'A') && (*c <= 'Z'))
+	{
+		*c = *c - 'A' + 'a';
+	}
+}
+
+int preguntar_n_en_rango(char *s, int min, int max)
+{
+	int n;
+
+	do
+	{
+		printf("%s [%d-%d]: ", s, min, max);
+		scanf("%d%*c", &n);
+	} while (fuera_de_rango(n, min, max));
+
+	return n;
+}
+
+int preguntar_si_o_no(char *s)
+{
+	char c;
+
+	do
+	{
+		printf("%s [s/n]: ", s);
+		scanf("%c%*c", &c);
+		convertir_a_minusculas(&c);
+	} while (c != 's' && c != 'n');
+
+	return (c == 's');
+}
diff --git a/preguntas.h b/preguntas.h
new file mode 100644
index 0000000..2cc6da6
--- /dev/null
+++ b/preguntas.h
@@ -0,0 +1,15 @@
+// Este fichero se le da al alumno
+#ifndef PREGUNTAS_H
+#define PREGUNTAS_H
+
+#include <stdio.h>
+
+#define TRUE 1
+#define FALSE 0
+
+int fuera_de_rango(int n, int min, int max);
+void convertir_a_minusculas(char *c);
+int preguntar_n_en_rango(char *s, int min, int max);
+int preguntar_si_o_no(char *s);
+
+#endif // PREGUNTAS_H
diff --git a/tirada.c b/tirada.c
new file mode 100644
index 0000000..ce398d8
--- /dev/null
+++ b/tirada.c
@@ -0,0 +1,122 @@
+#define TIRADA_H
+
+#include <stdio.h>
+#include "ficha.h"
+#include "jugador.h"
+#include "mesa.h"
+
+#define MAX_TIRADAS_JUGADOR NUM_FICHAS_DOMINO
+
+typedef struct
+{
+	int n_ficha;  // numero de ficha en el vector de fichas del jugador
+	char extremo; // IZQUIERDA o DERECHA (de n_ficha(1))
+	int girada;	  // TRUE o FALSE
+	int dobledobla;
+} t_tirada;
+
+typedef struct
+{
+	int n_tiradas;
+	t_tirada t[MAX_TIRADAS_JUGADOR];
+	int cont_dobles, dobleizquierda, doblederecha;
+
+} t_tiradas;
+
+void imprimir_tirada(t_tirada t, t_jugador j)
+{ //Siempre es visible independiente de omnisciencia
+	int aux;
+	aux = t.n_ficha;
+	if (j.tipo == T_ROBOT)
+		printf("Tira:  %c|%d:%d|\n\n", t.extremo, j.f[aux].num1, j.f[aux].num2);
+}
+
+void imprimir_tiradas(t_tiradas ts, t_jugador j, int visible)
+{
+	int i;
+
+	if ((visible == TRUE && j.tipo == T_ROBOT) || j.tipo == T_HUMANO)
+	{ // Muestra si omnisciencia está activada o el jugador es humano
+		printf("Tiradas posibles: ");
+		if (ts.n_tiradas > 0)
+		{ // Si puede tirar
+			for (i = 0; i < ts.n_tiradas; i++)
+			{
+				printf("%d(%c%d:%d) ", i, ts.t[i].extremo, j.f[ts.t[i].n_ficha].num1, j.f[ts.t[i].n_ficha].num2);
+			}
+
+			if ((ts.cont_dobles > 1) && (j.f[ts.t[ts.dobleizquierda].n_ficha].num1 != j.f[ts.t[ts.doblederecha].n_ficha].num2))
+			{
+				i = ts.n_tiradas;
+				printf("%d(%c%d:%d|%c%d:%d) ", i, ts.t[ts.dobleizquierda].extremo, j.f[ts.t[ts.dobleizquierda].n_ficha].num1, j.f[ts.t[ts.dobleizquierda].n_ficha].num2, ts.t[ts.doblederecha].extremo, j.f[ts.t[ts.doblederecha].n_ficha].num1, j.f[ts.t[ts.doblederecha].n_ficha].num2);
+			}
+			printf("\n");
+		}
+		else
+			printf("No hay tiradas posibles!!\n"); // Si no puede tirar
+	}
+}
+
+t_tiradas calcular_tiradas_posibles(t_jugador j, t_mesa m)
+{
+	t_tiradas ts;
+	int izq, der, i, k = 0, doble;
+	izq = extremo_izquierdo_mesa(m); // Calcula el extremo izquierdo de la mesa
+	der = extremo_derecho_mesa(m);	 // Calcula el extremo derecho de la mesa
+	ts.cont_dobles = 0;
+	for (i = 0; i < j.n_fichas; i++)
+	{
+		doble = 0;
+		if (j.f[i].num1 == j.f[i].num2)
+			doble = TRUE; // Comprueba si es un doble
+
+		if (j.f[i].num2 == izq)
+		{ // Tirada por la izquierda sin girar
+			if (doble == TRUE)
+			{
+				ts.cont_dobles++;
+				ts.dobleizquierda = k;
+			}
+			ts.t[k].n_ficha = i;
+			ts.t[k].extremo = 'i';
+			ts.t[k].girada = 0;
+			k++;
+		}
+		if (j.f[i].num1 == izq)
+		{ // Tirada por la izquierda girando
+			if (doble == FALSE)
+			{
+				ts.t[k].n_ficha = i;
+				ts.t[k].extremo = 'i';
+				ts.t[k].girada = 1;
+				k++;
+			}
+		}
+		if (j.f[i].num1 == der)
+		{ // Tirada por la derecha sin girar
+			if (doble == TRUE)
+			{
+				ts.cont_dobles++;
+				ts.doblederecha = k;
+			}
+			ts.t[k].n_ficha = i;
+			ts.t[k].extremo = 'd';
+			ts.t[k].girada = 0;
+			k++;
+		}
+		if (j.f[i].num2 == der)
+		{ // Tirada por la derecha girando
+			if (doble == FALSE)
+			{
+				ts.t[k].n_ficha = i;
+				ts.t[k].extremo = 'd';
+				ts.t[k].girada = 1;
+				k++;
+			}
+		}
+
+		ts.n_tiradas = k; // Numero de tiradas
+	}
+
+	return (ts);
+}
diff --git a/tirada.h b/tirada.h
new file mode 100644
index 0000000..c13c7f6
--- /dev/null
+++ b/tirada.h
@@ -0,0 +1,29 @@
+#ifndef TIRADA_H
+#define TIRADA_H
+
+#include "ficha.h"
+#include "jugador.h"
+#include "mesa.h"
+
+#define MAX_TIRADAS_JUGADOR NUM_FICHAS_DOMINO
+
+typedef struct
+{
+	int n_ficha;  // numero de ficha en el vector de fichas del jugador
+	char extremo; // IZQUIERDA o DERECHA (de n_ficha(1))
+	int girada;	  // TRUE o FALSE
+	int dobledobla;
+} t_tirada;
+
+typedef struct
+{
+	int n_tiradas;
+	t_tirada t[MAX_TIRADAS_JUGADOR];
+	int cont_dobles, doblederecha, dobleizquierda;
+} t_tiradas;
+
+void imprimir_tirada(t_tirada ts, t_jugador j);
+void imprimir_tiradas(t_tiradas ts, t_jugador j);
+t_tiradas calcular_tiradas_posibles(t_jugador j, t_mesa m);
+
+#endif // TIRADA_H