diff --git a/doc/qgames-code.txt b/doc/qgames-code.txt index 507b51c..459ac16 100644 --- a/doc/qgames-code.txt +++ b/doc/qgames-code.txt @@ -5,6 +5,11 @@ Hay dos tipos de instrucciones. Las de definicion del juego y las de las reglas. == Definicion del juego +# Define un tipo de movida nuevo. +# Si está la instrucción priority, indica que el tipo de movida es +# prioritaria y se intentará ejecutar primeramente +movetype: tipo_de_movida [priority] + == Reglas diff --git a/include/qgames.h b/include/qgames.h index ba45282..0410901 100644 --- a/include/qgames.h +++ b/include/qgames.h @@ -51,7 +51,7 @@ int qg_tipojuego_add_direccion_arr( Tipojuego* tj, char* direccion, int* int qg_tipojuego_add_link ( Tipojuego* tj, char* cas_ori, char* dir, char* cas_des ); int qg_tipojuego_add_color ( Tipojuego* tj, char* color ); int qg_tipojuego_set_control_repeticiones( Tipojuego* tj, int repeticiones ); -int qg_tipojuego_add_tipo_mov ( Tipojuego* tj, char* tipo_mov ); +int qg_tipojuego_add_tipo_mov ( Tipojuego* tj, char* tipo_mov, int prioritario ); int qg_tipojuego_add_tipopieza( Tipojuego* tj, char* tpieza ); int qg_tipojuego_add_tpieza_att( Tipojuego* tj, char* tpieza, char* att, int default_value ); int qg_tipojuego_add_zona ( Tipojuego* tj, char* zona ); diff --git a/lib/qgames.c b/lib/qgames.c index 8cde7c4..e05ee90 100644 --- a/lib/qgames.c +++ b/lib/qgames.c @@ -200,8 +200,8 @@ DLL_PUBLIC int qg_tipojuego_add_direccion_arr( Tipojuego* tj, char* dir DLL_PUBLIC int qg_tipojuego_add_color ( Tipojuego* tj, char* color ){ return tipojuego_add_color( tj, color ); } -DLL_PUBLIC int qg_tipojuego_add_tipo_mov ( Tipojuego* tj, char* tipo_mov ){ - return tipojuego_add_tipo_mov( tj, tipo_mov ); +DLL_PUBLIC int qg_tipojuego_add_tipo_mov ( Tipojuego* tj, char* tipo_mov, int priority ){ + return tipojuego_add_tipo_mov( tj, tipo_mov, priority ); } DLL_PUBLIC int qg_tipojuego_add_tipopieza( Tipojuego* tj, char* tpieza ){ return tipojuego_add_tipopieza( tj, tpieza ); diff --git a/parser/qgames_parser.y b/parser/qgames_parser.y index 5603ed4..4f2aa7d 100644 --- a/parser/qgames_parser.y +++ b/parser/qgames_parser.y @@ -125,7 +125,7 @@ void qgzprintf( char* format, ... ){ %token TOK_LOGO %token TOK_MARK %token TOK_MOVE -%token TOK_MOVETYPE +%token TOK_MOVETYPE TOK_PRIORITY %token TOK_NOTATION %token TOK_ONREPEAT %token TOK_ORIGIN @@ -156,6 +156,7 @@ void qgzprintf( char* format, ... ){ %token TOK_JUEGA TOK_JUEGA_SI %token TOK_GOTO_MARCA TOK_MARCA %token TOK_MUEVE TOK_MUEVE_SI +%token TOK_CONTINUA TOK_CONTINUA_SI %token TOK_IF %token TOK_OCUPADO %token TOK_OCUPADO_ENEMIGO @@ -691,6 +692,20 @@ instaction_juega: CHECK_TIPOJUEGO; if( !tipojuego_code_captura( tipojuego, NULL ) ) YYERROR; }; + +instaction_keep: + TOK_CONTINUA{ + CHECK_TIPOJUEGO; + NOT_IMPLEMENTED_WARN( "continua" ); + } | + TOK_CONTINUA word_or_string { + CHECK_TIPOJUEGO; + NOT_IMPLEMENTED_WARN( "continua tmov" ); + } | + TOK_CONTINUA_SI instexpr { + CHECK_TIPOJUEGO; + NOT_IMPLEMENTED_WARN( "continua si" ); + } ; instaction_para: @@ -823,6 +838,7 @@ instaction: instaction_break | instaction_crea | instaction_juega | + instaction_keep | instaction_final | instaction_if | instaction_set_marca | @@ -1073,9 +1089,15 @@ instruction_movetype: TOK_MOVETYPE word_or_string { CHECK_TIPOJUEGO; qgzprintf( "Definiendo %s", ((char*)$2) ); - qg_tipojuego_add_tipo_mov( tipojuego, ((char*)$2) ); + qg_tipojuego_add_tipo_mov( tipojuego, ((char*)$2), 0 ); free((void*)$2); - } + } | + TOK_MOVETYPE word_or_string TOK_PRIORITY { + CHECK_TIPOJUEGO; + qgzprintf( "Definiendo %s", ((char*)$2) ); + qg_tipojuego_add_tipo_mov( tipojuego, ((char*)$2), 1 ); + free((void*)$2); + } ; instruction_notation_element: TOK_PIECE_NAME { $$ = NOTACION_PIEZA; } | diff --git a/parser/qgames_scanner.l b/parser/qgames_scanner.l index 7d352ef..e6f26a8 100644 --- a/parser/qgames_scanner.l +++ b/parser/qgames_scanner.l @@ -133,6 +133,7 @@ origin { return TOK_ORIGIN; } onrepeat { return TOK_ONREPEAT; } piece\: { return TOK_PIECE; } piece{BAR}name { return TOK_PIECE_NAME; } +prior(ity)? { return TOK_PRIORITY ; } repeat { return TOK_REPEAT; } sequence\: { return TOK_SEQUENCE; } symmetry\: { return TOK_SYMMETRY; } @@ -214,6 +215,9 @@ define\: { define_created = 0; BEGIN(define_head); } change{BAR}color { return TOK_CAMBIA_COLOR; } create { return TOK_CREA; } goto{BAR}mark { return TOK_GOTO_MARCA; } +keep { return TOK_CONTINUA; } +keep{BAR}if { return TOK_CONTINUA_SI; } +keep{SPACES}if { return TOK_CONTINUA_SI; } initial-square { return TOK_CASILLERO_INICIAL; } mark { return TOK_MARCA; } move { return TOK_MUEVE; } diff --git a/src/movida.c b/src/movida.c index 9bc53f8..ff583b2 100644 --- a/src/movida.c +++ b/src/movida.c @@ -62,6 +62,18 @@ void movida_accion_crea ( Movida* mov, Tipopieza* tpieza, int color, Casiller list_agrega( mov->acciones, acc ); } +/* + * Indica que la movida actual continua + */ +void movida_accion_continua( Movida* mov, int tmov ){ + Accion* acc = accion_new(); + acc->tipo = ACCION_CONTINUA; + acc->tmov_continua = tmov; + mov->continua = 1; + if( !mov->acciones ) mov->acciones = list_nueva( NULL ); + list_agrega( mov->acciones, acc ); +} + /* * Esta es la generacion de accion de captura para una movida @@ -439,6 +451,9 @@ const char* movida_descripcion( Movida* mov ){ STREXPAND( ret, aloc, 6 ); strcat( ret, "pasar" ); break; + + case ACCION_CONTINUA: + break; default: mostrar = 0; @@ -509,22 +524,28 @@ int movida_dump( Movida* mov, void** data, int* size ){ Accion* acc = mov->acciones->data[i]; ADDDATA( ret, len, acc->tipo, aloc ); - len16 = acc->piece_number; - ADDDATA( ret, len, len16, aloc ); + if( acc->tipo == ACCION_CONTINUA ){ + len8 = acc->tmov_continua; + ADDDATA( ret, len, len8, aloc ); + } else { + len16 = acc->piece_number; + ADDDATA( ret, len, len16, aloc ); - len16 = acc->destino ? acc->destino->number : -1 ; - ADDDATA( ret, len, len16, aloc ); + len16 = acc->destino ? acc->destino->number : -1 ; + ADDDATA( ret, len, len16, aloc ); - len8 = acc->color; - ADDDATA( ret, len, len8, aloc ); + len8 = acc->color; + ADDDATA( ret, len, len8, aloc ); - len8 = acc->tpieza ? acc->tpieza->number : -1 ; - ADDDATA( ret, len, len8, aloc ); + len8 = acc->tpieza ? acc->tpieza->number : -1 ; + ADDDATA( ret, len, len8, aloc ); - len8 = acc->att_key; - ADDDATA( ret, len, len8, aloc ); + len8 = acc->att_key; + ADDDATA( ret, len, len8, aloc ); + + ADDDATA( ret, len, acc->att_val, aloc ); + } - ADDDATA( ret, len, acc->att_val, aloc ); } *data = ret; @@ -579,60 +600,69 @@ Movida* movida_load( Posicion* pos, void* data, int size ){ movida_free( mov ); return NULL; } + if( acc->tipo == ACCION_CONTINUA ){ + acc->tmov_continua = point[0]; + point ++; + if( ((char*)data) + size <= point ){ + LOGPRINT( 1, "Error tamaño puntero %p + %d <= %p", data, size, point ); + movida_free( mov ); + return NULL; + } + } else { + len16 = ((uint16_t*)point)[0]; + acc->piece_number = len16; + point += 2; + if( ((char*)data) + size <= point ){ + LOGPRINT( 1, "Error tamaño puntero %p + %d <= %p", data, size, point ); + movida_free( mov ); + return NULL; + } - len16 = ((uint16_t*)point)[0]; - acc->piece_number = len16; - point += 2; - if( ((char*)data) + size <= point ){ - LOGPRINT( 1, "Error tamaño puntero %p + %d <= %p", data, size, point ); - movida_free( mov ); - return NULL; - } - - len16 = ((uint16_t*)point)[0]; - if( len16 != (uint16_t)-1 ){ - acc->destino = (Casillero*)(pos->tjuego->casilleros->data[len16]); - } - point += 2; - if( ((char*)data) + size <= point ){ - LOGPRINT( 1, "Error tamaño puntero %p + %d <= %p", data, size, point ); - movida_free( mov ); - return NULL; - } + len16 = ((uint16_t*)point)[0]; + if( len16 != (uint16_t)-1 ){ + acc->destino = (Casillero*)(pos->tjuego->casilleros->data[len16]); + } + point += 2; + if( ((char*)data) + size <= point ){ + LOGPRINT( 1, "Error tamaño puntero %p + %d <= %p", data, size, point ); + movida_free( mov ); + return NULL; + } - acc->color = point[0]; - point ++; - if( ((char*)data) + size <= point ){ - LOGPRINT( 1, "Error tamaño puntero %p + %d <= %p", data, size, point ); - movida_free( mov ); - return NULL; - } + acc->color = point[0]; + point ++; + if( ((char*)data) + size <= point ){ + LOGPRINT( 1, "Error tamaño puntero %p + %d <= %p", data, size, point ); + movida_free( mov ); + return NULL; + } - len8 = point[0]; - if( len8 != (uint8_t)-1 ){ - acc->tpieza = (Tipopieza*)(pos->tjuego->tipo_piezas->data[len8]); - } - point ++; - if( ((char*)data) + size <= point ){ - LOGPRINT( 1, "Error tamaño puntero %p + %d <= %p", data, size, point ); - movida_free( mov ); - return NULL; - } + len8 = point[0]; + if( len8 != (uint8_t)-1 ){ + acc->tpieza = (Tipopieza*)(pos->tjuego->tipo_piezas->data[len8]); + } + point ++; + if( ((char*)data) + size <= point ){ + LOGPRINT( 1, "Error tamaño puntero %p + %d <= %p", data, size, point ); + movida_free( mov ); + return NULL; + } - acc->att_key = point[0]; - point ++; - if( ((char*)data) + size <= point ){ - LOGPRINT( 1, "Error tamaño puntero %p + %d <= %p", data, size, point ); - movida_free( mov ); - return NULL; - } - - acc->att_val = ((int*)point)[0]; - point += sizeof( int ); - if( ((char*)data) + size < point ){ - LOGPRINT( 1, "Error tamaño puntero %p + %d <= %p", data, size, point ); - movida_free( mov ); - return NULL; + acc->att_key = point[0]; + point ++; + if( ((char*)data) + size <= point ){ + LOGPRINT( 1, "Error tamaño puntero %p + %d <= %p", data, size, point ); + movida_free( mov ); + return NULL; + } + + acc->att_val = ((int*)point)[0]; + point += sizeof( int ); + if( ((char*)data) + size < point ){ + LOGPRINT( 1, "Error tamaño puntero %p + %d <= %p", data, size, point ); + movida_free( mov ); + return NULL; + } } list_agrega( mov->acciones, acc ); diff --git a/src/movida.h b/src/movida.h index 54fc418..642897b 100644 --- a/src/movida.h +++ b/src/movida.h @@ -14,14 +14,16 @@ typedef struct StrMovida { char* notacion; int tmov; int piece_number; - char continua; + char continua; // La movida continua (a nivel global). Casillero* destino; // Solo como auxiliar, no usar directamente, para eso esta movida_destino char* descripcion; } Movida; typedef struct StrAccion{ char tipo; + char continua; int piece_number; + int tmov_continua; Casillero* destino; int color; Tipopieza* tpieza; @@ -39,6 +41,7 @@ typedef struct StrAccion{ #define ACCION_DESTRUYE 5 #define ACCION_ASIGNA_ATT 6 #define ACCION_INFORMACION 7 +#define ACCION_CONTINUA 8 #define ACCION_PASAR 10 @@ -47,6 +50,7 @@ Movida* movida_dup( Movida* mov ); void movida_accion_mueve ( Movida* mov, Pieza* p, Casillero* destino ); void movida_accion_captura( Movida* mov, Pieza* p ); +void movida_accion_continua( Movida* mov, int tmov ); void movida_accion_crea ( Movida* mov, Tipopieza* tpieza, int color, Casillero* cas ); void movida_accion_transforma( Movida* mov, Pieza* p, int color, Tipopieza* tpieza ); void movida_accion_asigna_att( Movida* mov, Pieza* p, int att, int val ); diff --git a/src/simbolos.h b/src/simbolos.h index cb15096..07f1f40 100644 --- a/src/simbolos.h +++ b/src/simbolos.h @@ -22,7 +22,8 @@ typedef struct StrSimbolo{ #define SIM_ZONA 4 #define SIM_DIRECCION 5 #define SIM_TIPOMOV 6 -#define SIM_COLOR 7 +#define SIM_TIPOMOVP 7 +#define SIM_COLOR 8 extern int simbolo_id; diff --git a/src/tipojuego.c b/src/tipojuego.c index f19f455..783a407 100644 --- a/src/tipojuego.c +++ b/src/tipojuego.c @@ -282,14 +282,14 @@ int tipojuego_add_tpieza_att( Tipojuego* tj, char* tpieza, char* att, in * Esta funcion crea una nuevo tipo de movimiento * * */ -int tipojuego_add_tipo_mov( Tipojuego* tj, char* tmov ){ +int tipojuego_add_tipo_mov( Tipojuego* tj, char* tmov, int prioridad ){ if( !TJVALIDO(tj) ) return 0; if( tipojuego_get_simbolo( tj, tmov ) ){ TJSETERROR( tj, "Tipo de movimiento ya existente", tmov ); return 0; } tj->tipomovs ++; - SIM_ADD( tj, SIM_TIPOMOV, tmov, tj->tipomovs ); + SIM_ADD( tj, prioridad ? SIM_TIPOMOVP : SIM_TIPOMOV, tmov, tj->tipomovs ); return 1; } diff --git a/src/tipojuego.h b/src/tipojuego.h index 5d891e6..a7e169e 100644 --- a/src/tipojuego.h +++ b/src/tipojuego.h @@ -274,6 +274,7 @@ int tipojuego_add_direccion( Tipojuego* tj, char* direccion ); int tipojuego_add_direccion_rel( Tipojuego* tj, char* direccion, ... ); int tipojuego_add_direccion_arr( Tipojuego* tj, char* direccion, int* dirv ); int tipojuego_add_color ( Tipojuego* tj, char* color ); +int tipojuego_add_tipo_mov( Tipojuego* tj, char* tmov, int prioridad ); /* Funciones de acceso a datos de tipojuego */ Casillero* tipojuego_get_casillero_by_num( Tipojuego* tj, int nro ); diff --git a/src/tipojuego_gets_inline.h b/src/tipojuego_gets_inline.h index 7f7e68e..3cc75f1 100644 --- a/src/tipojuego_gets_inline.h +++ b/src/tipojuego_gets_inline.h @@ -96,6 +96,6 @@ static inline int tipojuego_get_tipomov ( Tipojuego* tj, char* tipomov Simbolo* sym; sym = tipojuego_get_simbolo( tj, tipomov ); if( !sym ) return NOT_FOUND; - if( sym->tipo != SIM_TIPOMOV ) return NOT_FOUND; + if( sym->tipo != SIM_TIPOMOV && sym->tipo != SIM_TIPOMOVP ) return NOT_FOUND; return sym->ref; } diff --git a/test/bin/test-generic.c b/test/bin/test-generic.c index bab9b5b..73960d4 100644 --- a/test/bin/test-generic.c +++ b/test/bin/test-generic.c @@ -43,7 +43,7 @@ int main( int argc, char** argv ){ assert( qg_tipojuego_valido( tj ) ); qg_tipojuego_add_casillero( tj, "n" ); assert( qg_tipojuego_valido( tj ) ); - qg_tipojuego_add_tipo_mov ( tj, "Tipo mov" ); + qg_tipojuego_add_tipo_mov ( tj, "Tipo mov", 0 ); qg_tipojuego_add_tipopieza( tj, "Gemagenerica" ); assert( qg_tipojuego_valido( tj ) ); assert( qg_tipojuego_add_tpieza_att( tj, "Gemagenerica", "att", 1 ) ); @@ -107,7 +107,7 @@ int main( int argc, char** argv ){ qg_tipojuego_add_casillero( tj, "a2" ); qg_tipojuego_add_color( tj, "verde" ); qg_tipojuego_add_color( tj, "negro" ); - assert( qg_tipojuego_add_tipo_mov( tj, "tmov" ) ); + assert( qg_tipojuego_add_tipo_mov( tj, "tmov", 1 ) ); assert( qg_tipojuego_add_secuencia( tj, "verde", NULL ) ); assert( qg_tipojuego_add_secuencia( tj, "verde", "tmov" ) ); assert( qg_tipojuego_add_secuencia( tj, "negro", NULL ) ); diff --git a/vm/qgames_code.c b/vm/qgames_code.c index e98d743..b771159 100644 --- a/vm/qgames_code.c +++ b/vm/qgames_code.c @@ -661,7 +661,7 @@ int tipojuego_start_code( Tipojuego* tj, char tiporegla, char* tipopiez printf( "Tipo movimiento %s inexistente (File %s - linea %d)\n", tipomov, __FILE__, __LINE__ ); exit( EXIT_FAILURE ); } - if( sm->tipo != SIM_TIPOMOV ){ + if( sm->tipo != SIM_TIPOMOV && sm->tipo != SIM_TIPOMOVP ){ printf( "%s no es tipo movimiento (File %s - linea %d)\n", tipomov, __FILE__, __LINE__ ); exit( EXIT_FAILURE ); }