示例#1
0
void tratarNuevoPersonaje(char* data) {
	char pId;

	pId = data[0];
	log_info(logFile, "Creando Personaje %c", pId);
	CrearPersonaje(listaPersonajes, pId, 0, 0, 1, orden);
	orden++;
	dibujar();
}
示例#2
0
int main(int argc, char* argv[]) {
    // Lo puse t0d0 en el llamado de abajo, no se porque y si se puede capturar 2 veces la señal como estaba hecho.
    // signal(SIGINT, notificarPersonajes);

    pthread_mutex_init(&semNiv, NULL);

    logger = logInit(argv, argv[1]);

    // Capturamos sigint y avisamos a los personajes para que cierren y cerramos el nivel.
    signal(SIGINT, cerrarForzado);

    t_config *configNivel;
    char** arrCaja;
    char* nom_nivel;
    char* ip_orq;
    char* port_orq;
    char* dir_orq;
    char ip[16];
    int puerto;

    //--Creamos el config
    configNivel = config_try_create(
                      //"nivel1.config" //Modo Debug
                      argv[1], "Nombre,orquestador,TiempoChequeoDeadlock,Recovery,ip,puerto,Caja1");

    ITEM_NIVEL *ListaItems = NULL;

    //--Creamos cada caja de recursos
    char* cajaAux;
    cajaAux = malloc(sizeof(char) * 6);
    sprintf(cajaAux, "Caja1");

    //--Inicializa la lista con los personajes y sus recursos
    personajes = list_create();
    personaje_t pjAux;

    int t = 1;
    int cols = 0;
    int rows = 0;
    int posXCaja = 0;
    int posYCaja = 0;
    nivel_gui_inicializar();
    // Conseguimos el area del nivel
    char state = nivel_gui_get_area_nivel(&cols, &rows);
    // Validamos que no haya habido error
    if (state != EXIT_SUCCESS) {
        cerrarNivel("Error al intentar conseguir el area del nivel (GUI).");
        exit(EXIT_FAILURE);
    }
    char* messageLimitErr;
    messageLimitErr = malloc(sizeof(char) * 100);

    //--Mientras pueda levantar el array
    while ((arrCaja = config_try_get_array_value(configNivel, cajaAux)) != NULL ) {
        posXCaja = atoi(arrCaja[3]);
        posYCaja = atoi(arrCaja[4]);
        // Validamos que la caja a crear esté dentro de los valores posibles del mapa
        if (posXCaja > rows || posYCaja > cols || posXCaja < 1 || posYCaja < 1) {
            sprintf(messageLimitErr, "La caja %c excede los limites de la pantalla. (%d,%d) - (%d,%d)", arrCaja[1][0], posXCaja, posYCaja, rows, cols);
            cerrarNivel(messageLimitErr);
            exit(EXIT_FAILURE);
        }
        // Si pasó la validacion, la creamos.
        CrearCaja(&ListaItems, arrCaja[1][0], atoi(arrCaja[3]), atoi(arrCaja[4]), atoi(arrCaja[2]));
        //--Rearma el cajaAux para la iteracion
        sprintf(cajaAux, "Caja%d", ++t);
    }

    free(cajaAux);

    //--Boludeces de los sockets
    message_t message;
    fd_set master, temp;
    struct sockaddr_in myAddress;
    struct sockaddr_in remoteAddress;
    int maxSock;
    int sockListener;
    int sockOrq;

    //--Saludo al orquestador

    //--Obetenemos el string del nombre y dirección del orquestador
    nom_nivel = config_get_string_value(configNivel, "Nombre");
    dir_orq = config_get_string_value(configNivel, "orquestador");
    puerto = config_get_int_value(configNivel, "puerto");
    memcpy(ip, config_get_string_value(configNivel, "ip"), 16);
    // Conseguimos el tiempo de espera de chequeo
    int tiempoChequeo = config_get_int_value(configNivel, "TiempoChequeoDeadlock");

    ip_orq = strtok(dir_orq, ":"); 	//--Separar ip
    port_orq = strtok(NULL, ":");	//--Separar puerto

    // Crear un socket:
    struct sockaddr_in socketInfo;
    if ((sockOrq = socket(AF_INET, SOCK_STREAM, 0)) != 0) {

        socketInfo.sin_family = AF_INET;
        socketInfo.sin_addr.s_addr = inet_addr(ip_orq);
        socketInfo.sin_port = htons(atoi(port_orq));

        // Conectar el socket con la direccion 'socketInfo'.
        if (connect(sockOrq, (struct sockaddr*) &socketInfo, sizeof(socketInfo)) == -1) {
            perror("Connect");
            exit(EXIT_FAILURE);
        }

        log_info(logger, "Conexión con orquestador.");

        orq_t orqMsj;
        orqMsj.type = NIVEL;
        orqMsj.detail = SALUDO;
        strcpy(orqMsj.name, nom_nivel);

        //memcpy(orqMsj.ip, &localhost->sin_addr.s_addr, 16);
        strcpy(orqMsj.ip, ip);
        orqMsj.port = puerto;

        //--Envía el "Saludo" para ser agregado
        if (send(sockOrq, &orqMsj, sizeof(orq_t), 0) == -1) {
            perror("Saludo");
            exit(EXIT_FAILURE);
        }
    }

    // Definimos los threads
    pthread_t thr_interbloqueos;
    paramInterbloqueo_t parametros;
    parametros.numSock = sockOrq;
    parametros.tiempoChequeo = tiempoChequeo;
    parametros.recovery = config_get_int_value(configNivel, "Recovery");

    // y los lanzamos
    if (pthread_create(&thr_interbloqueos, NULL, (void*) detectInterbloqueos, (void *) &parametros)) {
        log_error(logger, strerror(errno));
        exit(EXIT_FAILURE);
    }

    int maxRows, maxCols;
    int posX, posY;
    int posItemY, posItemX;
    int i;

    nivel_gui_get_area_nivel(&maxRows, &maxCols);

    nivel_gui_dibujar(ListaItems, nom_nivel);

    iniSocks(&master, &temp, &myAddress, remoteAddress, &maxSock, &sockListener, puerto, logger);
    while (1) {
        //--Gestiona un cliente ya conectado
        i = getSockChanged(&master, &temp, &maxSock, sockListener, &remoteAddress, &message, sizeof(message_t), logger);
        if (i != -1) {

            pthread_mutex_lock(&semNiv);

            int contPj;
            int contRec;
            char *auxRec;
            personaje_t *tempAux;
            //--Recibe mensaje y define comportamiento según el tipo
            switch (message.type) {
            case SALUDO:
                //--Agregamos personaje a la lista de items y a la de personajes/recursos
                CrearPersonaje(&ListaItems, i, message.name, INIX, INIY);
                pjAux.numSock = i;
                pjAux.chirimbolo = message.name;
                pjAux.blocked = false;
                pjAux.recursos = list_create();
                list_add_new(personajes, &pjAux, sizeof(personaje_t));

                //--Armamos la estrucura para enviar la posición inicial
                message.type = SALUDO;
                message.detail = INIX;
                message.detail2 = INIY;

                log_info(logger, "Se agregó el personaje %c con el socket %d", message.name, i);

                if (send(i, &message, sizeof(message), 0) == -1)
                    perror("Respuesta posición inicial");
                break;
            case POSICION:
                //--Obtiene posición del item pedido
                getPosRec(ListaItems, message.detail, &posX, &posY);

                //--Armamos la estrucura para enviar la posición del recurso pedido
                message.type = POSICION;
                message.detail = posX;
                message.detail2 = posY;

                if (send(i, &message, sizeof(message), 0) == -1)
                    perror("Respuesta posición recurso");
                break;
            case MOVIMIENTO:
                //--Devuelve las posiciones X e Y del item
                if (getPosPer(ListaItems, i, &posX, &posY) == -1)
                    perror("GetPosItem");

                switch (message.detail) {

                case ARRIBA:
                    if (posY > 1)
                        posY--;
                    break;

                case ABAJO:
                    if (posY < maxRows)
                        posY++;
                    break;

                case IZQUIERDA:
                    if (posX > 1)
                        posX--;
                    break;
                case DERECHA:
                    if (posX < maxCols)
                        posX++;
                    break;
                }

                //--Define confirmación y la devuelve
                message.type = MOVIMIENTO;
                message.detail2 = message.detail;
                message.detail = 1;
                if (send(i, &message, sizeof(message), 0) == -1)
                    perror("Confirmacion");

                //--Desbloquear en caso de que esté bloqueado
                for (contPj = 0; contPj < list_size(personajes); contPj++) {
                    tempAux = list_get(personajes, contPj);

                    if (tempAux->numSock == i && tempAux->blocked)
                        tempAux->blocked = false;
                }

                MoverPersonaje(ListaItems, i, posX, posY);
                break;
            case PEDIDO:
                //--Obtiene posición del item pedido y del personaje
                getPosRec(ListaItems, message.detail, &posItemX, &posItemY);
                getPosPer(ListaItems, i, &posX, &posY);

                //--Valida si llegó al recurso
                if ((posItemX == posX) && (posItemY == posY)) {

                    //-- Siempre le tiene que agregar a la lista de recursos, este o no bloqueado
                    //--Agrega el recurso a la lista de recursos del personaje
                    int contPj;
                    personaje_t* tempAux;
                    for (contPj = 0; contPj < list_size(personajes); contPj++) {
                        tempAux = list_get(personajes, contPj);

                        if (tempAux->numSock == i) {
                            list_add_new(tempAux->recursos, &(message.detail), sizeof(message.detail));
                            break;
                        }
                    }

                    //--Resta uno a la cantidad del item
                    int result = restarQuantityRec(ListaItems, message.detail);

                    if (result >= 0) {

                        log_info(logger, "A %d se le da el recurso %c", i, message.detail);

                        //--Si pudo restar la cantidad
                        tempAux->blocked = false;
                        //--Define confirmación y la devuelve
                        message.detail = 1;
                        if (send(i, &message, sizeof(message), 0) == -1)
                            perror("Confirmacion");

                    } else {
                        //--Si el recurso ya no tiene instacias
                        tempAux->blocked = true;

                        log_info(logger, "A %d se le niega el recurso %c", i, message.detail);
                        //--Define rechazo y lo devuelve
                        message.detail = 0;
                        if (send(i, &message, sizeof(message), 0) == -1)
                            perror("Confirmacion");
                    }
                } else {
                    log_error(logger, "Posicion erronea al pedir recurso");
                    exit(EXIT_FAILURE);
                }

                break;
            case SALIR:
                for (contPj = 0; contPj < list_size(personajes); contPj++) {
                    tempAux = list_get(personajes, contPj);

                    if (tempAux->numSock == i) {
                        //--Elimina y libera la lista de recursos de personaje

                        for (contRec = 0; contRec < list_size(tempAux->recursos); contRec++) {
                            auxRec = list_get(tempAux->recursos, contRec);
                            //--Suma la cantidad de recursos que el personaje libera
                            sumarQuantityRec(ListaItems, *auxRec, 1);
                        }

                        list_destroy_and_destroy_elements(tempAux->recursos, free);

                        //--Elimina y libera al personaje de la lista de personajes
                        list_remove_and_destroy_element(personajes, contPj, free);
                        BorrarPer(&ListaItems, i);
                        break;
                    }
                }

                log_debug(logger, "%d se desconectó", i);
                break;
            }
            nivel_gui_dibujar(ListaItems, nom_nivel);

            pthread_mutex_unlock(&semNiv);
        }

    }

    nivel_gui_terminar();
    return 0;
}
示例#3
0
void mensajesConPlataforma(int32_t socketEscucha) {//ATIENDE LA RECEPCION Y POSTERIOR RESPUESTA DE MENSAJES DEL ORQUESTADOR
	enum tipo_paquete unMensaje = PER_conexionNivel_ORQ;
	char* elMensaje=NULL;

	pthread_mutex_lock(&mutex_log);
	log_info(logger,"Voy a esperar recibir un mensaje de %d", socketEscucha);
	pthread_mutex_unlock(&mutex_log);

	pthread_mutex_lock(&mutex_mensajes); //(matyx)
	recibirMensaje(socketEscucha, &unMensaje,&elMensaje);
	pthread_mutex_unlock(&mutex_mensajes);

	sleep(1);

		pthread_mutex_lock(&mutex_log);
		log_info(logger, "Llego el tipo de paquete: %s .",obtenerNombreEnum(unMensaje));
		log_info(logger, "Llego este mensaje: %s .",elMensaje);
		pthread_mutex_unlock(&mutex_log);

		switch (unMensaje) {

			case PLA_movimiento_NIV: {//graficar y actualizar la lista RECIBE "@,1,3"

				char ** mens = string_split(elMensaje,",");

				char idPers = mens[0][0];


				if(huboCambios==true){

					pthread_mutex_lock(&mutex_log);
					log_info(logger,"envio los cambios de configuracion");
					pthread_mutex_unlock(&mutex_log);

					pthread_mutex_lock(&mutex_mensajes);
					enviarMensaje(socketDeEscucha, NIV_cambiosConfiguracion_PLA,buffer1);
					pthread_mutex_unlock(&mutex_mensajes);

					huboCambios=false;

					pthread_mutex_lock(&mutex_log);
					log_info(logger,"me preparo para recibir el ok");
					pthread_mutex_unlock(&mutex_log);

					pthread_mutex_lock(&mutex_mensajes);
					recibirMensaje(socketEscucha, &unMensaje,&elMensaje);
					pthread_mutex_unlock(&mutex_mensajes);

					pthread_mutex_lock(&mutex_log);
					log_info(logger,"deberia haber recibido el OK1");
					pthread_mutex_unlock(&mutex_log);

					if(unMensaje==OK1){
						pthread_mutex_lock(&mutex_log);
						log_info(logger,"ya envie el cambio de configuracion, y me dieron el ok");
						pthread_mutex_unlock(&mutex_log);

						if(existePersonajeEnListaItems(idPers)){

							pthread_mutex_lock(&mutex_listas);
							MoverPersonaje(items, idPers,atoi(mens[1]), atoi(mens[2]));
							pthread_mutex_unlock(&mutex_listas);

							pthread_mutex_lock(&mutex_log);
							log_info(logger, "El personaje %s se movio a %s %s ",mens[0],mens[1],mens[2]);
							pthread_mutex_unlock(&mutex_log);

							if(graficar)
								nivel_gui_dibujar(items,nombre);
							}

						pthread_mutex_lock(&mutex_mensajes);
						enviarMensaje(socketEscucha,NIV_movimiento_PLA,"0"); //"0" SI ES VALIDO
						pthread_mutex_unlock(&mutex_mensajes);


						} else {
							pthread_mutex_lock(&mutex_log);
							log_info(logger,"no recibi OK1,recibi cualquiera");
							pthread_mutex_unlock(&mutex_log);
						}
					} else {

						if(existePersonajeEnListaItems(idPers)){

							pthread_mutex_lock(&mutex_listas);
							MoverPersonaje(items, elMensaje[0],atoi(mens[1]), atoi(mens[2]));
							pthread_mutex_unlock(&mutex_listas);

							pthread_mutex_lock(&mutex_log);
							log_info(logger, "El personaje %s se movio a %s %s ",mens[0],mens[1],mens[2]);
							pthread_mutex_unlock(&mutex_log);

							if(graficar)
								nivel_gui_dibujar(items,nombre);
						}

						pthread_mutex_lock(&mutex_log);
						log_info(logger, "Confirmo que el personaje %s puede moverse",mens[0]);
						pthread_mutex_unlock(&mutex_log);

						pthread_mutex_lock(&mutex_mensajes);
						enviarMensaje(socketEscucha,NIV_movimiento_PLA,"0"); //"0" SI ES VALIDO
						pthread_mutex_unlock(&mutex_mensajes);

					}

				break;
			}
			case PLA_personajeMuerto_NIV:{ //RECIBE "@" MUERTE POR ENEMIGOS
				char id=elMensaje[0];
				t_personaje_niv1 * personaje = malloc(sizeof(t_personaje_niv1));

				personaje = buscarPersonajeListaPersonajes(listaPersonajesRecursos,string_substring_until(elMensaje,1));

				pthread_mutex_lock(&mutex_listas);
//				liberarRecursosDelPersonaje(personaje->recursosActuales); // tambien suma sus recursos a disponible
				borrarPersonajeListaPersonajes(listaPersonajesRecursos,elMensaje);

				pthread_mutex_unlock(&mutex_listas);

				pthread_mutex_lock(&mutex_log);
				log_info(logger, "El personaje %c ha muerto ",id);
				pthread_mutex_unlock(&mutex_log);



				break;
			}
			case PLA_nuevoPersonaje_NIV:{ //RECIBE "@" LA POSICION DE INICIO SERA SIEMPRE 0,0 POR LO QUE NO LA RECIBE


				char * simbolo = malloc(strlen(elMensaje)+1);
				strcpy(simbolo,elMensaje);

				pthread_mutex_lock(&mutex_listas);
				CrearPersonaje(items,elMensaje[0],0,0);
				pthread_mutex_unlock(&mutex_listas);

				//ACA CREO UNA LISTA DE PERSONAJES CON SUS RESPECTIVOS RECURSOS ASIGNADOS
				t_personaje_niv1 * personaje = malloc(sizeof(t_personaje_niv1));
				personaje->simbolo = string_substring_until(elMensaje,1);
				personaje->recursosActuales = list_create();
				personaje->recursoBloqueante = string_new();
				personaje->posicion = posicion_create_pos(0,0);
				personaje->ingresoSistema = ingresoAlSistema;
				ingresoAlSistema++;

				pthread_mutex_lock(&mutex_listas);
				list_add(listaPersonajesRecursos,personaje);
				pthread_mutex_unlock(&mutex_listas);

				if(graficar)
					nivel_gui_dibujar(items,nombre);

				pthread_mutex_lock(&mutex_log);
				log_info(logger, "El nuevo personaje %c se dibujo en el mapa",elMensaje[0]);
				pthread_mutex_unlock(&mutex_log);

				break;

			}
			case PLA_posCaja_NIV:{ // RECIBE "F" SI ESTA SOLICITANDO UNA FLOR, POR EJEMPLO

				char * pos = string_new();
				ITEM_NIVEL * caja = buscarRecursoEnLista(items, elMensaje);

				string_append(&pos, string_from_format("%d",caja->posx));
				string_append(&pos, ",");
				string_append(&pos, string_from_format("%d",caja->posy));

				pthread_mutex_lock(&mutex_log);
				log_info(logger,"enviare la posicion de la caja");
				pthread_mutex_unlock(&mutex_log);

				pthread_mutex_lock(&mutex_mensajes);
				enviarMensaje(socketEscucha, NIV_posCaja_PLA,pos); //"X,Y"
				pthread_mutex_unlock(&mutex_mensajes);

				pthread_mutex_lock(&mutex_log);
				log_info(logger, "Envio posicion del recurso %s coordenadas %s ",elMensaje,pos);
				pthread_mutex_unlock(&mutex_log);

				free(pos);
				break;

			}
			case PLA_solicitudRecurso_NIV:{ // LE CONTESTO SI EL RECURSOS ESTA DISPONIBLE




				// El mensaje de ejemplo es : "@,H"

				char * rta;
				bool hayRecurso = determinarRecursoDisponible (string_substring_from(elMensaje, 2)); //SI ESTA EL RECURSO TMB LO RESTA
				t_personaje_niv1 * pers = buscarPersonajeListaPersonajes(listaPersonajesRecursos, string_substring_until(elMensaje,1));

				if (hayRecurso){
					rta = "0";

					pthread_mutex_lock(&mutex_listas);
					list_add(pers->recursosActuales, string_substring_from(elMensaje, 2));
					pers->recursoBloqueante = string_new();

					pthread_mutex_unlock(&mutex_listas);

				}else{

					pthread_mutex_lock(&mutex_listas);
					pers->recursoBloqueante = string_substring_from(elMensaje, 2);
					rta = "1";
					pthread_mutex_unlock(&mutex_listas);
				}


				pthread_mutex_lock(&mutex_mensajes);
				enviarMensaje(socketEscucha, NIV_recursoConcedido_PLA,rta);//"0" CONCEDIDO, "1" NO CONCEDIDO
				pthread_mutex_unlock(&mutex_mensajes);

				break;
			}

			case PLA_personajesDesbloqueados_NIV:{//"5,@,#,....." recorro lista personaje recursos y actualizo recBloqueante a vacio
				char ** mens = string_split(elMensaje,",");
				int i;

				int cantPersonajes=atoi(mens[0]);
				for(i=1;i<=cantPersonajes;i++){
					char * unPersDesbloqueado=mens[i];

					t_personaje_niv1 * unPers=buscarPersonajeListaPersonajes(listaPersonajesRecursos,unPersDesbloqueado);

					pthread_mutex_lock(&mutex_listas);
					unPers->recursoBloqueante=string_new();
					pthread_mutex_unlock(&mutex_listas);

					pthread_mutex_lock(&mutex_log);
					log_info(logger, "Personajes %s desbloqueados",mens[i]);
					pthread_mutex_unlock(&mutex_log);

				}


				break;
			}

			case PLA_actualizarRecursos_NIV:{ //"3;F,1;C,3;....." actualizo la lista de recursos sumandole esas cantidades
				char ** mens = string_split(elMensaje,";");
				int cantRecursos= atoi(mens[0]);
				int i;
				pthread_mutex_lock(&mutex_log);
				log_info(logger, "Recursos desbloqueados: %s",elMensaje);
				pthread_mutex_unlock(&mutex_log);

				for(i=1;i<=cantRecursos;i++){
					char** mensajeIndividual= string_split(mens[i],",");
					pthread_mutex_lock(&mutex_listas);
					int cantidad=atoi(mensajeIndividual[1]);
					sumarRecurso(items, mensajeIndividual[0][0],cantidad);
					pthread_mutex_unlock(&mutex_listas);

					if(graficar)
						nivel_gui_dibujar(items,nombre);
				}


				break;
			}
			case PLA_nivelFinalizado_NIV:{  //recibe personaje que termino el nivel ej: "@"
				char id=elMensaje[0];
				t_personaje_niv1 * personaje = malloc(sizeof(t_personaje_niv1));

				personaje = buscarPersonajeListaPersonajes(listaPersonajesRecursos,string_substring_until(elMensaje,1));

				pthread_mutex_lock(&mutex_listas);
	//			liberarRecursosDelPersonaje(personaje->recursosActuales);
				BorrarItem(items,id);
				borrarPersonajeListaPersonajes(listaPersonajesRecursos,elMensaje);
				pthread_mutex_unlock(&mutex_listas);

				pthread_mutex_lock(&mutex_log);
				log_info(logger, "El personaje %c ha terminado el nivel ",id);
				pthread_mutex_unlock(&mutex_log);

				if(graficar){

					nivel_gui_dibujar(items,nombre);

				}

				break;
			}


			case PLA_perMuereInterbloqueo_NIV:{
				char id=elMensaje[0];
				t_personaje_niv1 * personaje = malloc(sizeof(t_personaje_niv1));

				personaje = buscarPersonajeListaPersonajes(listaPersonajesRecursos,string_substring_until(elMensaje,1));

				pthread_mutex_lock(&mutex_listas);
//				liberarRecursosDelPersonaje(personaje->recursosActuales);
				BorrarItem(items,id);
				borrarPersonajeListaPersonajes(listaPersonajesRecursos,elMensaje);
				pthread_mutex_unlock(&mutex_listas);

				pthread_mutex_lock(&mutex_log);
				log_info(logger, "El personaje %c ha muerto por interbloqueo ",id);
				pthread_mutex_unlock(&mutex_log);

				if(graficar)
					nivel_gui_dibujar(items,nombre);

				break;
			}

			case PLA_perMuereNaturalmente_NIV: {
				char id = elMensaje[0];
				t_personaje_niv1 * personaje = malloc(sizeof(t_personaje_niv1));

				personaje = buscarPersonajeListaPersonajes(listaPersonajesRecursos,string_substring_until(elMensaje, 1));

				pthread_mutex_lock(&mutex_listas);
				liberarRecursosDelPersonaje(personaje->recursosActuales);
				BorrarItem(items, id);
				borrarPersonajeListaPersonajes(listaPersonajesRecursos, elMensaje);
				pthread_mutex_unlock(&mutex_listas);

				pthread_mutex_lock(&mutex_log);
				log_info(logger, "El personaje %c ha muerto por causas externas", id);
				pthread_mutex_unlock(&mutex_log);

				if (graficar)
					nivel_gui_dibujar(items, nombre);

				break;
			}

			{
				default:
					pthread_mutex_lock(&mutex_log);
					log_info(logger, "Recibi mensaje inexistente, la ejecucion del nivel finalizara");
					pthread_mutex_unlock(&mutex_log);

					eliminarEstructuras();

					break;
			}


			free(elMensaje);

		}


}
void crearGuiPersonajes(void* item) {
	personaje* character = (personaje *) item;
	CrearPersonaje(&listaItems, *character->simbolo, character->lastPosition->x, character->lastPosition->y);
}