Fecha actual 22 Nov 2018 12:05

Motor de batallas, código fuente (muy técnico me temo)

Artículos en plan blog acerca de temas relacionados con ogArena, aunque no tan importantes como para estar en los apartados principales. Digamos, para curiosos.
asturcon3
Site Admin
Site Admin
Mensajes: 6125
Registrado: 12 Nov 2007 14:36
Alianza: aSACo, ofcourse

Motor de batallas, código fuente (muy técnico me temo)

Mensaje por asturcon3 » 30 Dic 2010 09:26

Siempre que sale el tema de hacer un simulador y yo respondo que paso mucho de mantener un programa para eso, saltan uno o varios que dicen que si tuvieran el algoritmo de las batallas podrían hacerlo. Bueno, vamos a verlo.

Primero, culturilla. El motor de batallas actual es un proyecto de Visual C++ que genera un ejecutable con un diálogo donde lo único útil que hay es un cuadro de texto grande donde se va mostrando lo que hace el programa (un log). Hay un timer, que cuando se pasa el tiempo comprueba si hay una batalla pendiente de ejecutar. Si no la hay, reprograma el timer a un número fijo de segundos o a lo que queda hasta la siguiente flota (el menor de ambos). Si hay batalla, el programa recupera de la base de datos una cadena tocha que contiene, separados por caracteres |, todos los elementos que intervienen en la batalla.

Con esa cadena, dividiéndola, genera su propia representación interna de la batalla y la ejecuta. Cuando acaba, y basándose en esa misma representación interna, genera llamadas a la base de datos para computar el robo, la creación de luna, y los reportes de batalla.

Bueno, pues voy a publicar aquí la parte del timer (una rutina en el diálogo) y la clase Motor.cpp que realiza toda la batalla. En principio creo que cualquier programador que realmente pretenda hacer un simulador debería tener más que suficiente con eso. Pero si no es así, comentádmelo.

A ver, el timer del diálogo:
Oculto:

Código: Seleccionar todo

void CogArenaMonitorDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: Agregue aquí su código de controlador de mensajes o llame al valor predeterminado
	KillTimer(m_nTimer);
	while (1) {
		CString tS,tId;
#ifdef _DEBUG
		if (0) { 
			tS="BATALLA|460|[4:48:12]|6090925| 000.00| 000.30|0|100000|0|-|A|827|CaPRiCoRN|217902|[4:47:18]|24|23|24|F|6090925|206|5425709|1360|165|9180|213|2043025|6800|1650|37400||D|92|asturcon3|460|[4:48:12]|25|22|24|P|460|202|4699776|18|32|1360|203|2125067|18|80|4080|206|301|1400|160|9180|207|16|3500|640|20400|208|14000|175|320|10200|209|1003|4|32|5440|210|1499834|0|3|340|214|1|700000|160000|3060000|221|1|35000000|32000000|1|401|691444|280|64|680|402|1939217|350|80|680|403|4527|875|320|2720|404|902|3850|640|11900|405|450|525|1600|2720|406|49242|10500|960|34000|407|1|4|6400|6800|408|1|4|32000|34000|";
		} else 
#endif
		{
			while (_T("ERROR") == (tId=theApp.callDelay())) {
				log(_T("reconectar"));
				conectar();
			}
			int segs=_ttoi(tId);
			if (segs>=0) {
				log(_T("."));
				m_nTimer=SetTimer(0,segs*(long)1000+1,NULL);
				return;
			}

			time_t osBinaryTime;  // C run-time time (defined in <time.h>)
			time( &osBinaryTime );
			CTime ahora(osBinaryTime);
			tId=tId.Mid(1);
			tS.Format(_T("idF=%s %s\r\n"),tId,ahora.Format("%d/%m %H:%M:%S"));
			log(tS);
			tS=theApp.callFlotaEvent(tId);
			// tS=theApp.callProcP(_T("flotaEvent"),tId);
		}
		if (tS.Left(8)=="BATALLA|") {
			log(tS.Trim());
			m_motor.batallar(tS);
		}
	}
}
Sintaxis de la cadena que toma como entrada:
Oculto:
(| es el separador, lo de (...)+ que hay en cada flota indica que lo de dentro de los paréntesis se repite tantas veces como tipos de naves haya)

Código: Seleccionar todo

BATALLA|códigoDePlanetaVíctima|Coordenadas|idFlotaQueLlega|IndicadorDeDefensaAEscombros(0/1)|PorcentajeEscombros|SePodríaCrearLunaAqui(0/1)|EscombrosPara1%luna|-|
Flota1: Bando(A de Atacante,D de Defensor)|idJugador|nick|planetaBase|coordenadas|tecno1|tecno2|tecno3|tipoId(F de Flota,P de Planeta)|idFlota/Planeta|
(tipoNave|numDeNaves|Ataque|Defensa|Blindaje|)+|
Flota 2:...
...
Como comentario, en la flota defensora se pasan también las defensas, del mismo modo (código de tipo, número, tecnos)
Y ya por fin, en todas partes del juego los elementos (edificios, naves, defensas, tecnos, objetos) se identifican con un código numérico, habitualmente llamado gid (GraphicID, supongo), se ve perfectamente en el juego al picar el nombre de una nave para ver su descripción)
El código principal de motor4.cpp (no me deja adjuntarlo como tal, asíq ue copio y pego)
Oculto:

Código: Seleccionar todo

// Motor4.cpp: archivo de implementación
//
#include "stdafx.h"
#include "ogArenaMonitor.h"
#include "Motor4.h"


// CMotor

CMotor4::CMotor4()
{
}

CMotor4::~CMotor4()
{
	if (m_pFuegoRapido) {
		for (int i=0;i<300;i++) if (m_pFuegoRapido[i]) free(m_pFuegoRapido[i]);
		free(m_pFuegoRapido);
	}
	if (m_costes) free(m_costes);


}

int orden4(const void *na, const void *nb)
{
	const TNave *a,*b;
	a=(const TNave *)na;
	b=(const TNave *)nb;
	if (!a->nGrupo) return b->nGrupo ? 1:0;
	if (a->rondaMuerta!=b->rondaMuerta) return (a->rondaMuerta > b->rondaMuerta) ? -1:1;
	if (a->capturada!=b->capturada) return (a->capturada<b->capturada) ? -1:1;
	if (a->blindaje!=b->blindaje) return (a->blindaje<b->blindaje) ? -1:1;
	if (a->escudo!=b->escudo) return (a->escudo<b->escudo) ? -1:1;
	return 0;
}

int ordenIndice(const void *na, const void *nb)
{
	const TIndiceGrupos *a,*b;
	a=(const TIndiceGrupos *)na;
	b=(const TIndiceGrupos *)nb;
	if (a->capturada!=b->capturada) return (a->capturada<b->capturada) ? -1:1;
	if (a->blindaje!=b->blindaje) return (a->blindaje<b->blindaje) ? -1:1;
	if (a->escudo!=b->escudo) return (a->escudo<b->escudo) ? -1:1;
	return 0;
}

int checkIndex(TIndiceGrupos *base,int nGrupos,TNave *grupos)
{
#ifdef _DEBUG
	int i;
	TNave *n; 
	for (i=0;i<nGrupos;i++) {
		if (i) ASSERT(ordenIndice(base+i-1,base+i)<=0);
		ASSERT(base[i].grupo>=0);
//		ASSERT(base[i].grupo<nGrupos); -- No es correcto, no se trata del mismo contador
		n=grupos+base[i].grupo;
		if (base[i].capturada!=-1) { // Flag grupo muerto antes
			ASSERT( n->escudo==base[i].escudo);
			ASSERT( n->blindaje==base[i].blindaje);
			ASSERT( n->capturada==base[i].capturada);
		}
	}
	return 1;
#else 
	return 1;
#endif
}

int buscaIndiceGrupos(TIndiceGrupos *base,int nGrupos,int capturada,int escudo,int blindaje,int buscar,int numGrupo=-1)
{
	TIndiceGrupos test;
	int inf,sup,centro,comp;
	TIndiceGrupos *p;
	test.capturada=capturada;
	test.escudo=escudo;
	test.blindaje=blindaje;
	inf=0;
	sup=nGrupos-1;
	while (inf<=sup) {
		centro=(inf+sup)/2;
		p=&base[centro];
		comp=ordenIndice(&test,p);
		if (!comp) { // Encontrado valor
			if (numGrupo==-1) return centro;
			inf=centro; // si se busca grupo concreto buscar atras y alante
			while (true) {
				if (base[inf].grupo==numGrupo) return inf;
				if (!inf) break;
				inf--;
				if (ordenIndice(&test,&base[inf])) break;
			}
			sup=centro;
			while (true) {
				sup++;
				if (sup>=nGrupos) break;
				if (ordenIndice(&test,&base[sup])) break;
				if (base[sup].grupo==numGrupo) return sup;
			}
			return -1;
		}
		if (comp<0) sup=centro-1;
		else inf=centro+1;
	}
	if (buscar==0) return -1;
	if (comp<0) return centro; // test es menor que centro, almacenar en centro
	return centro+1; // test es mayor que centro, devolver siguiente
}

void moveIndex(TIndiceGrupos *base,int nGrupos,int lPos,int newPos)
{
	TIndiceGrupos t;
	ASSERT(lPos>=0);
	ASSERT(newPos>=0);
	if (lPos==newPos) return;
	memcpy(&t,base+lPos,sizeof(TIndiceGrupos));
	if (newPos>lPos) {
		memcpy(base+lPos,base+lPos+1,sizeof(TIndiceGrupos)*(newPos-lPos));
	} else if (newPos<lPos) {
		memcpy(base+newPos+1,base+newPos,sizeof(TIndiceGrupos)*(lPos-newPos));
	}
	memcpy(base+newPos,&t,sizeof(TIndiceGrupos));
}

void CMotor4::batallar(CString &txt) 
{
	CString reporte,tS;
	int i,j,iFlota,iLin,m,n,nToks,gid,bando,nFlotas;
	__int64 navesA,navesD;
	int soloSondas=1,numSondasA=0,bEstampadaSondas=0; // Comprobacion rápida solosondas && numFR>numSondas->muerte directa
	__int64 numFRASondas=0;
	int talismanes;
	__int64 escombros1pc;
	DWORD inicio,fin;
	unsigned int seed;
	inicio=GetTickCount();
	seed=(unsigned int)inicio;
	tS.Format("srand(%u)",seed);
	log(tS);
	srand(seed);
#ifdef _DEBUG
	 srand(44505125);
#endif

	m_perdidas[0]=0;
	m_perdidas[1]=0;
	m_escombros[0] =m_escombros[1]=0;
	CString *toks=split("|",txt,n);
	ASSERT(n>6);
	CString batCP=toks[1];
	CString batCoords=toks[2];
	int idF=atoi(toks[3]);
	m_defEscombros=atof(toks[4]);
	m_porcEscombros=atof(toks[5]);
	int lunable=atoi(toks[6]);
	escombros1pc=_atoi64(toks[7]);
	if (n>8) talismanes=atoi(toks[8]);
	else talismanes=0;
	delete []toks;

	toks=split("|-|",txt,n);
	CString t=toks[1];
	delete []toks;
	CString *flotaStr=split("||",t,nFlotas);
	m_flotas[0]=new TFlotas[nFlotas]; m_flotas[1]=new TFlotas[nFlotas];
	time_t ahora; time(&ahora); reporte.Format("%li",ahora);
	m_totNaves=0;
	navesA=navesD=0;
	m_nFlotas[0]=m_nFlotas[1]=0;
	// comprobar muerte de sondas
	for (iFlota=0;iFlota<nFlotas;iFlota++) {
		toks=split("|",flotaStr[iFlota],nToks);
		bando=toks[0]=='A' ? 0:1;
		for (n=10;n<nToks-3;n+=5) {
			j=atoi(toks[n]); // gid
			i=atoi(toks[n+1]); // cant
			if (!bando) {
				if (j!=210) soloSondas=0; 
				else numSondasA+=i;
			}
			if (!soloSondas) break;
			if (bando) {
				if (m_pFuegoRapido[j-200]) 
					numFRASondas+=(__int64)i*m_pFuegoRapido[j-200][210-200];
			}
		}
		delete []toks;
	}
	bEstampadaSondas=soloSondas && numFRASondas>numSondasA;
	// Crear flotas y grupos de naves
	for (iFlota=0;iFlota<nFlotas;iFlota++) {
		toks=split("|",flotaStr[iFlota],nToks);
		bando=toks[0]=='A' ? 0:1;
		for (n=10;n<nToks-3;n+=5) {
			i=atoi(toks[n+1]);
			m_totNaves+=i;
			if (!bando) navesA+=i;
			else navesD+=i;
		}
		delete []toks;
	}
	m_batDivisor=1;
	while (m_totNaves>10000000 && navesA>100000 && navesD>100000) {
		m_batDivisor*=2;
		m_totNaves/=2; navesA/=2; navesD/=2;
	}
	m_totNaves=0; navesA=0; navesD=0;
	for (iFlota=0;iFlota<nFlotas;iFlota++) {
		toks=split("|",flotaStr[iFlota],nToks);
		bando=toks[0]=='A' ? 0:1;
		i=m_nFlotas[bando];
		m_flotas[bando][i].idJug=atoi(toks[1]);
		m_flotas[bando][i].nick=toks[2];
		m_flotas[bando][i].CP=atoi(toks[3]);
		m_flotas[bando][i].coords=toks[4];
		m_flotas[bando][i].tipoIdPlan=toks[8][0];
		m_flotas[bando][i].idJuego=atoi(toks[9]);
//		m_flotas[bando][i].ataques=(int *)calloc(500,sizeof(int));
//		m_flotas[bando][i].maxEscudos =(int *)calloc(500,sizeof(int));
//		m_flotas[bando][i].maxBlind=(int *)calloc(500,sizeof(int));
//		m_flotas[bando][i].tocadas=(TTocadas **)calloc(500,sizeof(TTocadas*));
		m_flotas[bando][i].capturas=(int *)calloc(500,sizeof(int));
		m_flotas[bando][i].vCapturas=m_flotas[bando][i].vPerdidas=0;
//		m_flotas[bando][i].blindajeIntacto=(int *)calloc(500,sizeof(int));
		m_flotas[bando][i].lineas=(TLinea *)calloc(50,sizeof(TLinea)); m_flotas[bando][i].nLineas=0;
		m_flotas[bando][i].ataques=(int *)calloc(500,sizeof(int));
		m_flotas[bando][i].escudos=(int *)calloc(500,sizeof(int));
		m_flotas[bando][i].blindajes=(int *)calloc(500,sizeof(int));
		for (n=10,iLin=0;n<nToks-3;n+=5,iLin++) {
			// t.Format("Flota %i %s %s*%s",iFlota,toks[0],toks[n],toks[n+1]);
			// log(t);
			gid=atoi(toks[n]);
			m_flotas[bando][i].lineas[iLin].gid=gid;
			m_flotas[bando][i].ataques[gid]=m_flotas[bando][i].lineas[iLin].ataques=atoi(toks[n+2]);
			m_flotas[bando][i].escudos[gid]=m_flotas[bando][i].lineas[iLin].maxEscudo=atoi(toks[n+3]);
			m_flotas[bando][i].blindajes[gid]=m_flotas[bando][i].lineas[iLin].maxBlindaje=atoi(toks[n+4]);
			m=atoi(toks[n+1]);
			m_flotas[bando][i].lineas[iLin].nGrupoOrig=m;
			m=m/m_batDivisor;
			if (!m) m=1;
			m_totNaves+=m;
			if (!bando) navesA+=m;
			else navesD+=m;
			m_flotas[bando][i].lineas[iLin].nGrupo=m_flotas[bando][i].lineas[iLin].nGrupoOrigDiv=m;
			if (m<5000000 && !bEstampadaSondas) { // Lineal
				m_flotas[bando][i].lineas[iLin].maxGrupos=-1;
				m_flotas[bando][i].lineas[iLin].grupos=(TNave *)calloc(m ? m:1,sizeof(TNave));
				m_flotas[bando][i].lineas[iLin].grupos[0].nGrupo=1;
				m_flotas[bando][i].lineas[iLin].grupos[0].blindaje=m_flotas[bando][i].lineas[iLin].maxBlindaje;
				for (j=1;j<m;j++) memcpy(&m_flotas[bando][i].lineas[iLin].grupos[j],&m_flotas[bando][i].lineas[iLin].grupos[0],sizeof(TNave));
				m_flotas[bando][i].lineas[iLin].nGrupos=m;
			} else { // Agrupado
				m_flotas[bando][i].lineas[iLin].maxGrupos=100;
				m_flotas[bando][i].lineas[iLin].grupos=(TNave *)calloc(100,sizeof(TNave));
				m_flotas[bando][i].lineas[iLin].grupos[0].nGrupo=m_flotas[bando][i].lineas[iLin].nGrupo;
				m_flotas[bando][i].lineas[iLin].grupos[0].blindaje=m_flotas[bando][i].lineas[iLin].maxBlindaje;
				m_flotas[bando][i].lineas[iLin].nGrupos=1;
				if (!bando && bEstampadaSondas) m_flotas[bando][i].lineas[iLin].grupos[0].blindaje=-1,m_flotas[bando][i].lineas[iLin].grupos[0].rondaMuerta=1;
			}
		}
		m_flotas[bando][i].nLineas=iLin;
		m_nFlotas[bando]++;
		reporte+="/"+toks[0]; for (n=2;n<=7;n++) reporte+="/"+toks[n];
		delete []toks;
	}
	delete []flotaStr;

	int ganador=0,ronda=1;
	int bAtaque=0;

	if (bEstampadaSondas) ganador=2,ronda=2;

//	fin=GetTickCount(); t.Format(_T("call cronoIns('%s',%f);"),_T("IniRondas"),(fin-inicio)/1000.0); log(t);
	for (;ronda<=7 && !ganador;ronda++) {
		TNave *iNave;
		//t.Format("Ronda %i ",ronda); 
		// log(t);
		m_navBandos[0]=m_navBandos[1]=0;
		for (bando=0;bando<=1;bando++) {
			for (iFlota=0;iFlota<m_nFlotas[bando];iFlota++) {
				for (iLin=0;iLin<m_flotas[bando][iFlota].nLineas;iLin++) {
					m_flotas[bando][iFlota].lineas[iLin].nGrupo=0;
					if (ronda==1) m_flotas[bando][iFlota].lineas[iLin].nav2grupos=NULL;
				}
			}
		}
		bAtaque=0;
		// maxEscudos+comprobar ataque
		for (bando=0;bando<=1;bando++) {
			for (iFlota=0;iFlota<m_nFlotas[bando];iFlota++) {
				for (iLin=0;iLin<m_flotas[bando][iFlota].nLineas;iLin++) {
					if (m_flotas[bando][iFlota].lineas[iLin].maxGrupos==-1) { // Lineal
						iNave=m_flotas[bando][iFlota].lineas[iLin].grupos;
						n=m_flotas[bando][iFlota].lineas[iLin].maxEscudo;
						m=0;
						for (i=m_flotas[bando][iFlota].lineas[iLin].nGrupos;i;i--,iNave++) {
							if (iNave->blindaje>=0) {
								iNave->escudo=n;
								m++;
							} else {
								if (!iNave->rondaMuerta) iNave->rondaMuerta=ronda-1;
							}
						}
						m_flotas[bando][iFlota].lineas[iLin].nGrupo=m;
						m_navBandos[bando]+=m;
						if (!bAtaque && !bando && m) bAtaque=m_flotas[bando][iFlota].lineas[iLin].ataques;
					} else {
						if (m_flotas[bando][iFlota].lineas[iLin].nav2grupos) { 
							free(m_flotas[bando][iFlota].lineas[iLin].nav2grupos);
							m_flotas[bando][iFlota].lineas[iLin].nav2grupos=NULL;
						}
						for (i=0;i<m_flotas[bando][iFlota].lineas[iLin].nGrupos;i++) {
							iNave=&m_flotas[bando][iFlota].lineas[iLin].grupos[i];
							if (iNave->blindaje>=0) {
								iNave->escudo=m_flotas[bando][iFlota].lineas[iLin].maxEscudo;
								m_flotas[bando][iFlota].lineas[iLin].nGrupo+=iNave->nGrupo;
								m_navBandos[bando]+=iNave->nGrupo;
								if (!bAtaque && !bando) bAtaque=m_flotas[bando][iFlota].lineas[iLin].ataques;
							} else {
								if (!iNave->rondaMuerta) iNave->rondaMuerta=ronda-1;
							}
						}
						qsort(&m_flotas[bando][iFlota].lineas[iLin].grupos[0],m_flotas[bando][iFlota].lineas[iLin].nGrupos,sizeof(TNave),orden4);
						for (n=0,i=1;i<m_flotas[bando][iFlota].lineas[iLin].nGrupos;i++) {
							if (m_flotas[bando][iFlota].lineas[iLin].grupos[i].nGrupo) {
								if (!m_flotas[bando][iFlota].lineas[iLin].grupos[i].rondaMuerta 
									&& !m_flotas[bando][iFlota].lineas[iLin].grupos[n].rondaMuerta
									&& m_flotas[bando][iFlota].lineas[iLin].grupos[i].capturada==m_flotas[bando][iFlota].lineas[iLin].grupos[n].capturada
									&& m_flotas[bando][iFlota].lineas[iLin].grupos[i].blindaje==m_flotas[bando][iFlota].lineas[iLin].grupos[n].blindaje) {
										m_flotas[bando][iFlota].lineas[iLin].grupos[n].nGrupo+=m_flotas[bando][iFlota].lineas[iLin].grupos[i].nGrupo;
										m_flotas[bando][iFlota].lineas[iLin].grupos[i].nGrupo=0;
								} else {
									n++;
									if (i!=n) 
										memcpy(&m_flotas[bando][iFlota].lineas[iLin].grupos[n],&m_flotas[bando][iFlota].lineas[iLin].grupos[i],sizeof(TNave));
								}
							}
						}
						m_flotas[bando][iFlota].lineas[iLin].nGrupos=n+1;
					}
				}
			}
		}
		if (!m_navBandos[0]) ganador=2;
		else if (!m_navBandos[1] && bAtaque) ganador=1;
		if (ganador) break;
		if (ronda==7) break;

		if (!batDispara(ronda)) break;
//		fin=GetTickCount(); t.Format(_T("call cronoIns('%s',%f);"),_T("Disparos"),(fin-inicio)/1000.0); log(t);
		if (bAtaque==0 && m_navBandos[1]==0) break; // Empate si nada contra nada, despues de batDispara para q saque disparos en reporte
	}
	//t.Format("Fin de batalla, rondas=%i, atacantes=%i, defensores=%i\r\n",ronda,m_navBandos[0],m_navBandos[1]); 
	// log(t);
	for (bando=0; bando<=1; bando++) 
		for (iFlota=0;iFlota<m_nFlotas[bando];iFlota++)
			navesMuertas(bando,iFlota);
//	fin=GetTickCount(); t.Format(_T("call cronoIns('%s',%f);"),_T("Muertas"),(fin-inicio)/1000.0); log(t);

	for (i=1;i<=ronda;i++) {
		t.Format("/%i",i); reporte+=t;
		for (bando=0;bando<=1;bando++) 
			for (iFlota=0;iFlota<m_nFlotas[bando];iFlota++) 
				reporte+="/"+battFl(bando,iFlota,i==1,i);
		if ((ganador && i==ronda) || i==7) break;
		for (n=0;n<2;n++) {
			t.Format("/%s/%I64i/%I64i/%I64i",n ? "DD":"DA",m_rondas[i].disparos[n],m_rondas[i].fuerza[n],m_rondas[i].absor[n]);
			reporte+=t;
		}
	}
	i=reporte.GetLength();
	t.Format("/F/%i",ganador); reporte+=t;
//	fin=GetTickCount(); t.Format(_T("call cronoIns('%s',%f);"),_T("Info1"),(fin-inicio)/1000.0); log(t);
	if (ganador==1) {
		// Robo
		t.Format("%i",idF);
		t=theApp.callRobo(t);
		toks=split("|",t,n);
		reporte+="/R";
		for (i=0;i<n;i++) reporte+="/"+toks[i];
		delete []toks;
	}
	t.Format("/PA/%I64i",m_perdidas[0]);
	reporte+=t;
	t.Format("/PD/%I64i",m_perdidas[1]);
	reporte+=t;
	t.Format("/ES/%I64i/%I64i",m_escombros[0],m_escombros[1]);
	reporte+=t;
	__int64 esc=m_escombros[0] +m_escombros[1];
	int diamLuna=0,porcLuna;
	if (lunable && esc>=escombros1pc) {
		if (esc>20*escombros1pc) porcLuna=20;
		else porcLuna=(int)(esc/escombros1pc);
		porcLuna=porcLuna > 20 ? 20:porcLuna;
		t.Format("/L/%i",porcLuna); reporte+=t;
		// Check creacion luna
		do {
			if ((rand()*1.0/RAND_MAX)<porcLuna/100.0) {
				reporte+="/NL";
				diamLuna=400*porcLuna;
				break;
			}
		} while (talismanes--);
	}
//	fin=GetTickCount(); t.Format(_T("call cronoIns('%s',%f);"),_T("Info2"),(fin-inicio)/1000.0); log(t);
	if (reporte.GetLength()>1024) {
		theApp.callProc("reporteIni","","reporteIni");
		for (i=0;i<reporte.GetLength();i+=1024) 
			theApp.callProc("reporteAdd","'"+reporte.Mid(i,1024)+"'","reporteAdd");
		reporte="REPORTE";
	}


	t.Format("%i,%i,'%s',%I64i,%I64i,%I64i,%I64i,%i,%i",
		idF,ganador,reporte,m_escombros[0],m_escombros[1],m_perdidas[0],m_perdidas[1],diamLuna,ronda);
	theApp.callProc("eg_FinBatalla",t,"eg_FinBatalla");
//	fin=GetTickCount(); t.Format(_T("call cronoIns('%s',%f);"),_T("Fin"),(fin-inicio)/1000.0); log(t);
	log("Finalizado\r\n");
	for (bando=0;bando<2;bando++) {
		for (iFlota=0;iFlota<m_nFlotas[bando];iFlota++) {
			for (iLin=0;iLin<m_flotas[bando][iFlota].nLineas;iLin++) {
				delete []m_flotas[bando][iFlota].lineas[iLin].grupos;
			}
			delete []m_flotas[bando][iFlota].capturas;
			delete []m_flotas[bando][iFlota].lineas;
			delete []m_flotas[bando][iFlota].ataques;
			delete []m_flotas[bando][iFlota].escudos;
			delete []m_flotas[bando][iFlota].blindajes;
		}
		delete []m_flotas[bando];
	}

	fin=GetTickCount();
	t.Format(_T("'Batalla',%f"),(fin-inicio)/1000.0);
	theApp.callProc("cronoIns",t,"cronos");
	log(t);
}

CString CMotor4::battFl(int bando,int iFlota,bool bExtraInfo,int ronda)
{
	int *gids=(int *)calloc(600,sizeof(int));
	int *tot=(int *)calloc(600,sizeof(int));
	int *nGrupo=(int *)calloc(600,sizeof(int));
	int *nOrig=(int *)calloc(600,sizeof(int));

	int nNave,i,iLin;
	for (iLin=0;iLin<m_flotas[bando][iFlota].nLineas;iLin++) {
		nGrupo[m_flotas[bando][iFlota].lineas[iLin].gid]+=m_flotas[bando][iFlota].lineas[iLin].nGrupoOrigDiv;
		nOrig[m_flotas[bando][iFlota].lineas[iLin].gid]+=m_flotas[bando][iFlota].lineas[iLin].nGrupoOrig;
		for (nNave=0;nNave<m_flotas[bando][iFlota].lineas[iLin].nGrupos;nNave++) {
			TNave *iNave=&m_flotas[bando][iFlota].lineas[iLin].grupos[nNave];
			if (bExtraInfo) {
				if (iNave->rondaMuerta)
					tot[m_flotas[bando][iFlota].lineas[iLin].gid]+=iNave->nGrupo;
			}
			if (!iNave->rondaMuerta || iNave->rondaMuerta>=ronda) 
				gids[m_flotas[bando][iFlota].lineas[iLin].gid]+=iNave->nGrupo;
		}
	}
	if (m_batDivisor>1) {
		for (i=0;i<600;i++) {
			if (nOrig[i]) {
				if (tot[i]==nGrupo[i]) tot[i]=nOrig[i];
				else tot[i]*=m_batDivisor;
				if (gids[i]==nGrupo[i]) gids[i]=nOrig[i];
				else gids[i]*=m_batDivisor;
			}
		}
	}
	CString ret,t;
	for (i=0;i<600;i++) if (gids[i]) { t.Format("%i/",i); ret+=t; }
	if (ret=="") {
		ret="0";
	} else {
		ret+="/";
		for (i=0;i<600;i++) if (gids[i]) { t.Format("%i/",gids[i]); ret+=t; }
		ret+="/";
		if (bExtraInfo) {
			for (i=0;i<600;i++) if (gids[i]) { t.Format("%i/",m_flotas[bando][iFlota].ataques[i]); ret+=t; }
			ret+="/";
			for (i=0;i<600;i++) if (gids[i]) { t.Format("%i/",m_flotas[bando][iFlota].escudos[i]); ret+=t; }
			ret+="/";
			for (i=0;i<600;i++) if (gids[i]) { t.Format("%i/",m_flotas[bando][iFlota].blindajes[i]); ret+=t; }
			ret+="/";
			for (i=0;i<600;i++) if (gids[i]) { t.Format("%i/",tot[i]); ret+=t; }
			ret+="/";
			if (m_flotas[bando][iFlota].vPerdidas) { t.Format("P/%I64i/",m_flotas[bando][iFlota].vPerdidas); ret+=t; }
			if (m_flotas[bando][iFlota].vCapturas) { t.Format("C/%I64i/",m_flotas[bando][iFlota].vCapturas); ret+=t; }
		}
	}
	free(gids); free(tot); 
	return ret;
}

void CMotor4::init(void) 
{
	CRecordset r(&theApp.m_db);
	CDBVariant v;
	m_pFuegoRapido=(int **)calloc(300,sizeof(int *));
	for (int i=0;i<300;i++) m_pFuegoRapido[i]=NULL;
	r.Open(-1,_T("select * from fuegoRapido"));
	while (!r.IsEOF()) {
//		r.GetFieldValue((short)0,v);
		r.GetFieldValue((short)0,v,SQL_C_SLONG);
		int gidA=v.m_iVal;
		if (!m_pFuegoRapido[gidA-200]) m_pFuegoRapido[gidA-200]=(int *)calloc(300,sizeof(int));
		r.GetFieldValue(1,v,SQL_C_SLONG);
		int gidD=v.m_iVal;
		r.GetFieldValue(2,v,SQL_C_SLONG);
		int n=v.m_iVal;
		m_pFuegoRapido[gidA-200][gidD-200]=n;
		r.MoveNext();
	}
	r.Close();
	log(_T("Cargados fuegos rápidos\r\n"));

	m_costes=(TCoste *)calloc(300,sizeof(TCoste));
	r.Open(-1,_T("select gid,costeM_gid,costeC_gid,costeD_gid from gids where gid between 200 and 499"));
	while (!r.IsEOF()) {
		r.GetFieldValue((short)0,v,SQL_C_SLONG);
		int gid=v.m_iVal;
		r.GetFieldValue(1,v,SQL_C_SLONG); 
		m_costes[gid-200].costeM=v.m_lVal;
		r.GetFieldValue(2,v,SQL_C_SLONG); 
		m_costes[gid-200].costeC=v.m_lVal;
		r.GetFieldValue(3,v,SQL_C_SLONG); 
		m_costes[gid-200].costeD=v.m_lVal;
		r.MoveNext();
	}
	r.Close();
	log(_T("Cargados costes\r\n"));
}

void CMotor4::log(CString txt)
{
	theApp.log(txt);
}

void CMotor4::navesMuertas(int bando,int iFlota)
{
	int *muertas=(int *)calloc(600,sizeof(int));
	int *capturadas=(int *)calloc(600,sizeof(int));
	int *grupo=(int *)calloc(600,sizeof(int));
	int *reales=(int *)calloc(600,sizeof(int));
	int nNave,iLin,gid,i;
	__int64 n,muertasi,nPerd;

	for (iLin=0;iLin<m_flotas[bando][iFlota].nLineas;iLin++) {
		for (nNave=0;nNave<m_flotas[bando][iFlota].lineas[iLin].nGrupos;nNave++) {
			gid=m_flotas[bando][iFlota].lineas[iLin].gid;
			TNave *iNave=&m_flotas[bando][iFlota].lineas[iLin].grupos[nNave];
			if (iNave->rondaMuerta) {
				if (iNave->capturada) 
					capturadas[gid]+=iNave->nGrupo;
				else muertas[gid]+=iNave->nGrupo;
			}
		}
		grupo[gid]+=m_flotas[bando][iFlota].lineas[iLin].nGrupoOrigDiv;
		reales[gid]+=m_flotas[bando][iFlota].lineas[iLin].nGrupoOrig;
	}
	CString ret,t,sql;
	for (i=0;i<600;i++) {
		if (muertas[i]+capturadas[i]) { 
			n=(__int64)(muertas[i]+capturadas[i]);
			muertasi=(__int64)muertas[i];
			if (m_batDivisor>1) {
				if (n==grupo[i]) n=reales[i];
				else n*=m_batDivisor;
				if (muertasi==grupo[i]) muertasi=reales[i];
				else muertasi*=m_batDivisor;
			}
			nPerd=n*(m_costes[i-200].costeM+m_costes[i-200].costeC+m_costes[i-200].costeD);
			m_perdidas[bando]+=nPerd;
			m_flotas[bando][iFlota].vPerdidas+=nPerd;
			if (i<400) {
				m_escombros[0]+=(__int64)(muertasi*(m_costes[i-200].costeM*m_porcEscombros));
				m_escombros[1]+=(__int64)(muertasi*(m_costes[i-200].costeC*m_porcEscombros));
			} else {
				m_escombros[0]+=(__int64)(muertasi*(m_costes[i-200].costeM*m_defEscombros));
				m_escombros[1]+=(__int64)(muertasi*(m_costes[i-200].costeC*m_defEscombros));
			}
			sql.Format("'%c',%i,%i,%i",
				m_flotas[bando][iFlota].tipoIdPlan,m_flotas[bando][iFlota].idJuego,i,n);
			theApp.callProc("eg_FinBatFl",sql,"FinBatFl");
		}
	}
	for (i=0;i<500;i++) {
		if(n=m_flotas[bando][iFlota].capturas[i]) {
			if (m_batDivisor>1) {
				if (n==grupo[i]) n=reales[i];
				else n*=m_batDivisor;
			}
			sql.Format("'%c',%i,%i,%i",
				m_flotas[bando][iFlota].tipoIdPlan,m_flotas[bando][iFlota].idJuego,i,-n);
			m_flotas[bando][iFlota].vCapturas+=(__int64)(n*(m_costes[i-200].costeM+m_costes[i-200].costeC+m_costes[i-200].costeD));
			theApp.callProc("eg_FinBatFl",sql,"FinCapturas");
		}
	}
	sql.Format("'%c',%i,%i,%i",
		m_flotas[bando][iFlota].tipoIdPlan,m_flotas[bando][iFlota].idJuego,-1,0);
	theApp.callProc("eg_FinBatFl",sql,"FinCapturas");
	free(muertas); free(capturadas);
	free(grupo); free(reales);
}

int CMotor4::fuegoRapido(int gidA,int gidD)
{
	if (!m_pFuegoRapido[gidA-200]) return 0;
	int n=m_pFuegoRapido[gidA-200][gidD-200];
	if (!n) return 0;
	if (!(rand()%n)) {
		return 0;
	}
	return 1;
}

int CMotor4::almacenar(TLinea * pvLinea,TNave *vNave,int iGrV,int iVict,
	int escudo,int blinda,unsigned __int8 capturada) 
{
	int iH,vAGrupo,n,m;
	TIndiceGrupos *pig;
	TNave * tNave;
	if (vNave->blindaje<0) { // Ya estaba muerta de antes
		;
	} else {
		if (pvLinea->maxGrupos==-1) { // Array lineal
			vNave->blindaje=blinda;
			vNave->escudo=escudo;
			vNave->capturada=capturada;
		} else {
			iH=-1; vAGrupo=-1;
			if (vNave->nGrupo==1) {
				n=-1;
				if (pig=pvLinea->indiceGrupos) {
					n=buscaIndiceGrupos(pvLinea->indiceGrupos,pvLinea->nIndiceGrupos,vNave->capturada,vNave->escudo,vNave->blindaje,0,iGrV);
					ASSERT(pvLinea->grupos[pig[n].grupo].blindaje==vNave->blindaje);
					ASSERT(pvLinea->grupos[pig[n].grupo].escudo==vNave->escudo);
					ASSERT(pvLinea->grupos[pig[n].grupo].capturada==vNave->capturada);
					DEBUG_ONLY(checkIndex(pvLinea->indiceGrupos,pvLinea->nIndiceGrupos,pvLinea->grupos));
				}
				vNave->blindaje=blinda;
				vNave->escudo=escudo;
				vNave->capturada=capturada;
				if (n!=-1) {
					m=buscaIndiceGrupos(pvLinea->indiceGrupos,pvLinea->nIndiceGrupos,vNave->capturada,vNave->escudo,vNave->blindaje,-1);
					pig[n].blindaje=blinda;
					pig[n].capturada=capturada;
					pig[n].escudo=escudo;
					moveIndex(pvLinea->indiceGrupos,pvLinea->nGrupos,n,m);
					DEBUG_ONLY(checkIndex(pvLinea->indiceGrupos,pvLinea->nIndiceGrupos,pvLinea->grupos));
				}
			} else {
				if (pvLinea->indiceGrupos) {
					vAGrupo=buscaIndiceGrupos(pvLinea->indiceGrupos,pvLinea->nIndiceGrupos,capturada,escudo,blinda,0);
					if (vAGrupo!=-1) {
						vAGrupo=pvLinea->indiceGrupos[vAGrupo].grupo; tNave=&pvLinea->grupos[vAGrupo];
						n=0;
						if (tNave->escudo == escudo)
						if (tNave->blindaje ==blinda) 
						if (!tNave->rondaMuerta) 
						if (tNave->capturada==capturada) 
							n=1;
						if (n==0) 
							ASSERT(0);
					}
				} else {
					for (vAGrupo=0,tNave=&pvLinea->grupos[0];vAGrupo<pvLinea->nGrupos;vAGrupo++,tNave++) {
						if (!tNave->nGrupo) {
							if (iH==-1) iH=vAGrupo;
						} else {
							if (tNave->escudo == escudo)
							if (tNave->blindaje ==blinda) 
							if (!tNave->rondaMuerta) 
							if (tNave->capturada==capturada) 
								break;
						}
					}
					if (vAGrupo>=pvLinea->nGrupos) vAGrupo=-1;
				}
				if (vAGrupo!=-1) { // traspasar
					pvLinea->grupos[vAGrupo].nGrupo++;
					vNave->nGrupo--;
					if (pvLinea->nav2grupos) pvLinea->nav2grupos[-iVict-1]=vAGrupo;
				} else { // Nuevo grupo
					if (iH==-1) { // no hay sitio, ampliar
						iH=pvLinea->nGrupos;
						pvLinea->nGrupos++;
						if (iH>=pvLinea->maxGrupos) {
							pvLinea->maxGrupos+=1000;
							pvLinea->grupos=(TNave *)realloc(pvLinea->grupos,(pvLinea->maxGrupos)*sizeof(TNave));
							if (!pvLinea->grupos) { log("Sin memoria"); return 0; }
							memset(&pvLinea->grupos[iH],0,1000*sizeof(TNave));
							vNave=NULL; // en principio no me hace falta. Ojo movido
							if (pig=pvLinea->indiceGrupos) {
								pig=(TIndiceGrupos *)realloc(pig,(pvLinea->maxGrupos)*sizeof(TIndiceGrupos));
								if (!pig) free(pvLinea->indiceGrupos);
								pvLinea->indiceGrupos=pig;
							}
						}
					}
					memcpy(&pvLinea->grupos[iH],&pvLinea->grupos[iGrV],sizeof(TNave));
					pvLinea->grupos[iGrV].nGrupo--;
					pvLinea->grupos[iH].nGrupo=1;
					pvLinea->grupos[iH].blindaje=blinda;
					pvLinea->grupos[iH].escudo=escudo;
					pvLinea->grupos[iH].capturada=capturada;
					if (pvLinea->nav2grupos) 
						pvLinea->nav2grupos[-iVict-1]=iH;
					if (pig=pvLinea->indiceGrupos) {
						n=buscaIndiceGrupos(pvLinea->indiceGrupos,pvLinea->nIndiceGrupos,capturada,escudo,blinda,1);
						if (n>0) {
							if ((pig[n-1].blindaje>blinda && pig[n-1].capturada==capturada) || pig[n-1].blindaje<-1) 
								ASSERT(0);
						}
						if (n<pvLinea->nIndiceGrupos-1) {
							if ((pig[n+1].blindaje<blinda && pig[n+1].capturada==capturada) || pig[n+1].blindaje<-1)
								ASSERT(0);
						}


						if (n<pvLinea->nIndiceGrupos) memmove(pig+n+1,pig+n,sizeof(TIndiceGrupos)*(pvLinea->nIndiceGrupos-n));
						pig[n].blindaje=blinda;
						pig[n].escudo=escudo;
						pig[n].capturada=capturada;
						pig[n].grupo=iH;
						pvLinea->nIndiceGrupos++;
						DEBUG_ONLY(checkIndex(pvLinea->indiceGrupos,pvLinea->nIndiceGrupos,pvLinea->grupos));
						ASSERT(n==buscaIndiceGrupos(pvLinea->indiceGrupos,pvLinea->nIndiceGrupos,capturada,escudo,blinda,0,iH));
					}
				}
			}
		}
	}
	return 1;
}

int CMotor4::batDispara(int ronda)
{
	int fuego,fuego2;
	int navesMuertas[2];
	int nGrupo;
	int navesAhorro=0;
	int iH,iVict,bando,fr,n,*pi;

	int iFl,iLin,iGr; TFlotas *pFlota; TLinea *pLinea; TNave *iNave;
	int iFlV,iLiV,iGrV; TFlotas *pvFlota; TLinea *pvLinea; TNave * vNave;
	TIndiceGrupos *pig;

	unsigned __int8 capturada;
	bool bMuerta;
	TRondas *pRonda=&m_rondas[ronda];
	DWORD inicio,fin;

	pRonda->n=ronda;
	pRonda->disparos[0]=pRonda->disparos[1]=0;
	pRonda->fuerza[0]=pRonda->fuerza[1]=0;
	pRonda->absor[0]=pRonda->absor[1]=0;
	navesMuertas[0]=navesMuertas[1]=0;
	for (bando=0;bando<2;bando++) {
		TRACE("Ronda %d bando %d",ronda,bando);
		inicio=GetTickCount();
		for (iFl=0;iFl<m_nFlotas[1-bando];iFl++) {
			pFlota=&m_flotas[1-bando][iFl];
			for (iLin=0;iLin<pFlota->nLineas;iLin++) {
				pLinea=&pFlota->lineas[iLin];
				pLinea->nav2grupos=NULL;
				if (pLinea->nGrupo>=10000000) TRACE(" Uf(%d)",pLinea->nGrupo);
				if (pLinea->maxGrupos==-1) { // Array lineal de naves
					pLinea->indiceGrupos=NULL;
					n=sizeof(int)*pLinea->nGrupo;
					pi=pLinea->nav2grupos=(int *)malloc(n);
					if (pi) {
						for (iGrV=0;iGrV<pLinea->nGrupos;iGrV++) {
							if (!pLinea->grupos[iGrV].rondaMuerta)
								*(pi++)=iGrV;
						}
					}
				} else { // Naves agrupadas
					if (pLinea->nGrupo<25000000 && pLinea->nGrupo>0) { // Array directo
						n=sizeof(int)*pLinea->nGrupo;
						pi=pLinea->nav2grupos=(int *)malloc(n);
						if (pi) {
							for (iGrV=0;iGrV<pLinea->nGrupos;iGrV++) {
								if (!pLinea->grupos[iGrV].rondaMuerta)
									for (n=pLinea->grupos[iGrV].nGrupo;n;n--) *(pi++)=iGrV;
							}
						}
						n=sizeof(TIndiceGrupos)*pLinea->maxGrupos;
						pig=pLinea->indiceGrupos=(TIndiceGrupos *)malloc(n);
						pLinea->nIndiceGrupos=0;
						if (pig) {
							for (iGrV=0;iGrV<pLinea->nGrupos;iGrV++) {
								if (!pLinea->grupos[iGrV].rondaMuerta) {
									pig[iGrV].blindaje=pLinea->grupos[iGrV].blindaje;
									pig[iGrV].escudo=pLinea->grupos[iGrV].escudo;
									pig[iGrV].capturada=pLinea->grupos[iGrV].capturada;
								} else {
									pig[iGrV].blindaje=0;
									pig[iGrV].escudo=0;
									pig[iGrV].capturada=-1; // que no se mezcle con otros grupos
									pig[iGrV].grupo=iGrV;
								}
								pig[iGrV].grupo=iGrV;
								pLinea->nIndiceGrupos++;
							}
							qsort(pig,pLinea->nIndiceGrupos,sizeof(TIndiceGrupos),ordenIndice);
						}
					}
				}
			}
		}
		for (iFl=0;iFl<m_nFlotas[bando];iFl++) {
			pFlota=&m_flotas[bando][iFl];
			for (iLin=0;iLin<pFlota->nLineas;iLin++) {
				pLinea=&pFlota->lineas[iLin];
				for (iGr=0;iGr<pLinea->nGrupos;iGr++) {
					iNave=&pLinea->grupos[iGr];
					if (!iNave->rondaMuerta) {
						if (navesMuertas[1-bando]>=m_navBandos[1-bando]) continue; // No hay naves enemigas vivas, paso
						nGrupo=iNave->nGrupo; if (!nGrupo) nGrupo=1;
						ASSERT(nGrupo>=0);
						for (;nGrupo;nGrupo--) {
							fuego=fuego2=m_flotas[bando][iFl].lineas[iLin].ataques;
							if (!fuego) break;
							for (fr=0;;fr++) {
								fuego=fuego2=m_flotas[bando][iFl].lineas[iLin].ataques;
								iVict=rand();
								if (m_navBandos[1-bando]>RAND_MAX) iVict=iVict*(1+RAND_MAX)+rand(); 
								iVict%=m_navBandos[1-bando];
								iH=iVict;
								iVict=iH;

								for (iFlV=0;iFlV<m_nFlotas[1-bando];iFlV++) {
									pvFlota=&m_flotas[1-bando][iFlV];
									for (iLiV=0;iLiV<pvFlota->nLineas;iLiV++) {
										pvLinea=&pvFlota->lineas[iLiV];
										if (pvLinea->nGrupo>iVict) {
											if (pvLinea->maxGrupos==-1) { //Array lineal
												iGrV=pvLinea->nav2grupos[iVict];
												iVict=-1;
											} else {
												if (pvLinea->nav2grupos) {
													iGrV=pvLinea->nav2grupos[iVict];
													iVict=-iVict-1;
												} else {
													n=0;
													for (iGrV=0;iGrV<pvLinea->nGrupos;iGrV++) {
														if (!pvLinea->grupos[iGrV].rondaMuerta) {
															iVict-=pvLinea->grupos[iGrV].nGrupo;
															n+=pvLinea->grupos[iGrV].nGrupo;
															if (n>pvLinea->nGrupo)
																ASSERT(0);
															if (iVict<0) break;
														}
														else 
															iVict=iVict;
													}
												}
											}
											if (iVict>=0)
												ASSERT(0);
											if (iVict<0) break;
										} else {
											iVict-=pvLinea->nGrupo;
										}
									}
									if (iVict<0) break;
								}
								if (pvLinea->maxGrupos==-1) vNave=&pvLinea->grupos[iGrV];
								else vNave=&m_flotas[1-bando][iFlV].lineas[iLiV].grupos[iGrV];
								// mina térmica
								if (pLinea->gid==223) {
									// victima coste igual o inferior a crucero
									if (m_costes[pvLinea->gid-200].costeM+m_costes[pvLinea->gid-200].costeC+m_costes[pvLinea->gid-200].costeD<=29000) {
										fuego=fuego2=2*(vNave->escudo+vNave->blindaje);
										almacenar(pLinea,iNave,iGr,-iGr-1,0,-1,0); 
										navesMuertas[bando]++;
									} else {
										fuego=fuego2=0;
									}
								}
								pRonda->disparos[bando]++;
								pRonda->fuerza[bando]+=fuego;
								int escudo,blinda,maxBlinda,maxEscudo;
								capturada=vNave->capturada;
								maxEscudo=pvLinea->maxEscudo;
								maxBlinda=pvLinea->maxBlindaje;
								escudo=vNave->escudo;
								blinda=vNave->blindaje;
								if (escudo>0) {
									if (fuego<escudo) {
										pRonda->absor[bando]+=fuego;
									} else {
										pRonda->absor[bando]+=escudo;
									}
								}
								if (fuego<escudo) {
									int perc=(int)((100.0*fuego)/maxEscudo);
									fuego=maxEscudo*perc;
									fuego/=100;
									fuego2=fuego;
								}
								if (escudo<=0 || fuego>0) {
									fuego-=escudo;
									escudo-=fuego2;
									if (fuego<0) fuego=0;
								} else fuego=0;
								if (escudo<0) escudo=0;
								bMuerta=false;
								if (fuego>0) {
									if (blinda>=0) {
										if ((blinda-=fuego)<0) blinda=-1;
										else {
											if (blinda<0.7*maxBlinda) {
												if ((rand()%100) >(100*blinda)/maxBlinda) blinda=-1;
											}
										}
										if (blinda==-1) { // Nave murio con este disparo
											if (pLinea->gid==222 && pvLinea->gid<400 && pvLinea->gid!=212 && pvLinea->gid!=223) { // y no es defensa ni sat ni mina
												capturada=1;
												pFlota->capturas[pvLinea->gid]++;
											}
											navesMuertas[1-bando]++;
											bMuerta=true;
										}
									}
								}
								if (!almacenar(pvLinea,vNave,iGrV,iVict,escudo,blinda,capturada)) return 0;
								if (bMuerta) {
									if (navesMuertas[1-bando]>=m_navBandos[1-bando]) {
										// Cortar iteraciones, ya no quedan enemigas
										 nGrupo=1; // Salir del bucle de naves atacantes agrupadas
										 break; // Salir de fuegos rápidos
									}
								}
								if (!fuegoRapido(pLinea->gid,pvLinea->gid)) break;
							}
						}
					}
				}
			}
		}
		for (iFl=0;iFl<m_nFlotas[1-bando];iFl++) {
			pFlota=&m_flotas[1-bando][iFl];
			for (iLin=0;iLin<pFlota->nLineas;iLin++) {
				pLinea=&pFlota->lineas[iLin];
				if (pLinea->nav2grupos) free(pLinea->nav2grupos);
				pLinea->nav2grupos=NULL;
				if (pLinea->indiceGrupos) free(pLinea->indiceGrupos);
				pLinea->indiceGrupos=NULL;
			}
		}
		fin=GetTickCount();
		TRACE(" %f secs\n",(fin-inicio)/1000.0);
	}
	return 1;
}
Mmmm ¿qué me queda?

Ah, sí, los fuegos rápidos. Se cargan una sola vez al inicio del programa, y son un array tal que m_pFuegoRapido[atacante-200][defensor-200]=fuegoRápido. El -200 es porque las naves están numeradas a partir del 200, y no es plan de gastar memoria para guardar fuegos rápidos de edificios.

Y por cierto, la parte de guardar en memoria la representación de las naves y su agrupación por daño sufrido durante la batalla... es un dolor. Me puse ciego a porros para hacerlo, así que si no lo entendéis ya sabéis el método xD Como pista, hay dos o tres formas de guardar la batalla en memoria según lo grande que sea, pues las formas más eficientes en velocidad gastan más memoria, y viceversa. Así que el programa estima y decide por una de ellas. Y la de batallas realmente grandes, es realmente complicada xD
Bueno, creo que está completo el código, así que debería funcionar sin problemas.

Hale, ya tenéis comida. Ahora respondo personales :)

EDIT 20/1/2011: El .h, por las estructuras, es:
Oculto:

Código: Seleccionar todo

#pragma once

struct TCoste {	int costeM,costeC,costeD; }; 

struct TIndiceGrupos { int escudo,blindaje,grupo; __int8 capturada; };

struct TNave { 
	unsigned __int8 rondaMuerta:3,capturada:1;
	__int32 nGrupo;
	int escudo, blindaje;
};

class TLinea {
public:
	__int16 gid;
	__int32 nGrupo;
	__int32 nGrupoOrig,nGrupoOrigDiv; // Naves en flota inicial y divididas
	int maxEscudo,maxBlindaje,ataques;
	int *nav2grupos;
	TIndiceGrupos *indiceGrupos; int nIndiceGrupos;
	TNave *grupos; int nGrupos,maxGrupos;
};

class TFlotas { 
public:
	int bando,idJuego,idJug,CP;
	__int64 vPerdidas,vCapturas;
	int *capturas;
	char tipoIdPlan;
	CString nick,coords;
	TLinea *lineas; int nLineas;
	int *ataques,*escudos,*blindajes;
};

struct TRondas { int n; __int64 disparos[2],fuerza[2],absor[2]; };


// Destino del comando de CMotor

class CMotor4 
{
public:
	CMotor4();
	virtual ~CMotor4();

	void init(void);
	void batallar(CString &txt);

private:
	int almacenar(TLinea * pvLinea,TNave *vNave,int iGrV,int iVict,int escudo,int blinda,unsigned __int8 capturada);
	CString battFl(int bando,int iFlota,bool bExtraInfo,int ronda);
	int batDispara(int ronda);
	void log(CString txt);

	int *(*m_pFuegoRapido);
	TCoste *m_costes;
	__int64 m_perdidas[2],m_escombros[2],m_navBandos[2];
	__int64 m_totNaves;
	TFlotas *m_flotas[2]; int m_nFlotas[2];
	TRondas m_rondas[10];
	double m_defEscombros;
	double m_porcEscombros;
	bool m_lunable;
	void navesMuertas(int bando,int iFlota);
	int fuegoRapido(int gidA,int gidD);
	int m_batDivisor;
};


Imagen

Avatar de Usuario
ZoeDoGaM
Site Admin
Site Admin
Mensajes: 935
Registrado: 12 Nov 2007 14:45
Alianza: Ken Lee
Ubicación: donde asturcon3 :P
Contactar:

Re: Motor de batallas, código fuente (muy técnico me temo)

Mensaje por ZoeDoGaM » 31 Dic 2010 14:23

Si, si... tu libera códigos, verás lo que tardan los alemanes en llevárselo... XD.
Saludos.
Gotas de agua en tristeza y un poquito de sal para mis penas de princesa.
Imagen
Pero no te alarmes que ahora vuelvo.
¡Malditos seáis los fantasmas, jugáis con ventaja, doléis de verdad!.

C.sheppard
Helper Anime/Manga&Pelis/Series
Helper Anime/Manga&Pelis/Series
Mensajes: 3344
Registrado: 05 Dic 2010 11:03
Ubicación: Calle Falsa 456
Contactar:

Re: Motor de batallas, código fuente (muy técnico me temo)

Mensaje por C.sheppard » 31 Dic 2010 15:41

ZoeDoGaM escribió:Si, si... tu libera códigos, verás lo que tardan los alemanes en llevárselo... XD.
Saludos.

:lol: :lol: :lol: pues eh, sin broma xDD a my el año pasado un niño aleman me robo un codigo de mejora de un juego T_T (era una caca al final, asike no paso nada =))

Avatar de Usuario
darksexluzbel
Mensajes: 1502
Registrado: 04 Dic 2008 17:24
Alianza: good luck Soldier, O

Re: Motor de batallas, código fuente (muy técnico me temo)

Mensaje por darksexluzbel » 31 Dic 2010 16:42

ZoeDoGaM escribió:Si, si... tu libera códigos, verás lo que tardan los alemanes en llevárselo... XD.
Saludos.
Pus ya le piratearon el Trasladar Planeta no xD?
Imagen
Imagen
Imagen

el telible exanime
Helper Literatura
Helper Literatura
Mensajes: 3691
Registrado: 09 Nov 2009 16:49
Alianza: SCORPION
Ubicación: Leyendo

Re: Motor de batallas, código fuente (muy técnico me temo)

Mensaje por el telible exanime » 02 Ene 2011 01:32

darksexluzbel escribió:
ZoeDoGaM escribió:Si, si... tu libera códigos, verás lo que tardan los alemanes en llevárselo... XD.
Saludos.
Pus ya le piratearon el Trasladar Planeta no xD?
si, pero buscando lucro, hay que tener materia oscura... malditos alemanes xD
Jugar al ogarena es tan o mas dificil que montar un mueble de Ikea.

"LOS MÁS JOVENES, LOS MÁS SPAMMERS" by me

Imagen
gracias danyell

Imagen

Imagen
Imagen
miren el spoiler, vale la pena

Andurino
Mensajes: 67
Registrado: 18 Dic 2008 05:22

Re: Motor de batallas, código fuente (muy técnico me temo)

Mensaje por Andurino » 02 Ene 2011 22:13

asturcon3 escribió:
Sintaxis de la cadena que toma como entrada:
Oculto:
(| es el separador, lo de (...)+ que hay en cada flota indica que lo de dentro de los paréntesis se repite tantas veces como tipos de naves haya)

Código: Seleccionar todo

BATALLA|códigoDePlanetaVíctima|Coordenadas|idFlotaQueLlega|IndicadorDeDefensaAEscombros(0/1)|PorcentajeEscombros|SePodríaCrearLunaAqui(0/1)|EscombrosPara1%luna|-|
Flota1: Bando(A de Atacante,D de Defensor)|idJugador|nick|planetaBase|coordenadas|tecno1|tecno2|tecno3|tipoId(F de Flota,P de Planeta)|idFlota/Planeta|
(tipoNave|numDeNaves|Ataque|Defensa|Blindaje|)+|
Flota 2:...
...
Esto es lo que te estaba pidiendo de las paginas php (desconocemos su proceso interno, que es privado y NO NECESITAMOS).
La sintaxis de la decodificacion de las cadenas tH, tC;
fichero.tH[ ¿que es esto?:tipo dato | ¿que es esto?:tipo dato | ....]

Por cierto y si te interesa tengo la preview de la lectura de TODOS LOS TH,TC de TODAS LAS PAGINAS en aproximadamente 2 segundos. Obteniendo un sistema , que ya te he dicho NO ES ADECUADO NI CONVENIENTE, con estado permanente en memoria. Y actualizable por timer. Ah, no sale "dejame descansar"....

Estoy en la fase 2: -> Establecer un entorno estatico o permanente y actualizable (bd privada con XML). De aqui surguiran los datos a compartir con la aliaza y donde se guardaran de forma permanete. El medio de actualizar los datos compartidos sera mediante mesaje circurlar con [tag] especifico , inteligible para ojos profanos. Si sera legible con la igu correspondiente.

Como sigo sin disponer de la informacion de la sintaxis, me invente una.
-pagina.datos = {th:[split], tc:[split]}

Que no sea por reiterarlo. El metodo de acceso que me OBIGAS ha hacer , para demostrar no se que cosa, ES INCONVENIENTE E INADECUADO. ¿Porque?

Es JS, codigo abierto, tienes acceso a todo, simplemente piensa que mal uso se puede hacer.
¿Realmente tengo que publicarlo? Tu diras...

Por otra parte, hacer un simulador o cualquier otra cosa sin un Metodo de Acceso controlado y el desconocimiento de las sintaxis de los datos, en fin.. Simplemente es programar para el aire. Por cierto me resulta dificil ver el sentido de un motor de batallas ya que yo solo veo dos matrices con una operacion algo expecial.¿Puedes explicar la necesidad del motor tal y como lo tienes planteado?, otros != a ogarena no usan aplicaciones en C/C++ siembargo son funcionales.

Los DATOS solo sirven como una [SINTAXIS-DEL-TODO-CONOCIDO], por separado para cuestiones parciales VISION-GENERAL, FLOTA , ETC .
// Aqui es donde quizas te rompa los esquemas, pensando que necesitamos tener acceso a la totalidad de los datos en 1 LECTURA. TE INSISTO, eso es FALSO. SE Necesita la Totalidad de las SINTAXIS.

//Otra historia es el metodo de acceso a los datos al servidor. Cuestion que es irrelevante de momento (aunque me obligas a hacerlo de un modo inadecuado). Aqui probablemente habra que realizar objetos con eventos de acceso a los datos que solicite el usuario (usuario != (navegador|cliente)), pero eso es inecesario por el momento. Solamente , presupongo que habra que hacerlo por conjutos ya que de otro modo estariamos pasando bits o quijotes. Ademas de prevenir usos inapropiados o accesos reiterados.

Un saludo.

Avatar de Usuario
metallica
Mensajes: 106
Registrado: 11 Mar 2009 19:56

Re: Motor de batallas, código fuente (muy técnico me temo)

Mensaje por metallica » 03 Ene 2011 07:32

Andurino escribió:
asturcon3 escribió:
Es JS, codigo abierto, tienes acceso a todo, simplemente piensa que mal uso se puede hacer.
¿Realmente tengo que publicarlo? Tu diras...

.
Si tanto te gusta programar, ¿porqué no te programas tu propio juego y dejas de tocar las narices al personal?
Última edición por asturcon3 el 03 Ene 2011 08:39, editado 1 vez en total.
Razón: Arreglar los quotes. Yo no dije eso, fue él xD

Andurino
Mensajes: 67
Registrado: 18 Dic 2008 05:22

Codigo fuente en php de un Motor de Batallas

Mensaje por Andurino » 03 Ene 2011 15:27

Código: Seleccionar todo

<?php



/**

 * CombatEngine.php

 *

 * @version 1

 * @copyright 2008 By Chlorel

 */





// Tech : A : 11  B : 11  C : 13



// Points de structure  	4.000

// Puissance du bouclier 	10

// Valeur d'attaque	 	50



// A : 105

// B :  21

// C : 920



// 204 => array('metal'=>3000   ,'crystal'=>1000   ,'deuterium'=>0      ,'energy'=>0,'factor'=>1,'consumption'=>20  ,'speed'=>12500    ,'capacity'=>50

//             ,'shield'=>10   ,'attack'=>50    ,'sd'=>array(202=>2,203=>1,204=>1,205=>1,206=>1,207=>1,208=>1,209=>1,210=>5,211=>1,212=>5,213=>1,214=>1,215=>1,401=>1,402=>1,403=>1,404=>1,405=>1,406=>1,407=>1,408=>1)),



// Attaque  : 'Valeur Attaque' + (( 'Valeur Attaque' * 'Technologie Armes' ) / 10 )

// Bouclier : arrondi ('Puissance du bouclier' + (( 'Puissance du bouclier' * 'Technologie Bouclier' ) / 10 ))

// Coque    : Points de structure + (( Points de structure * 'Technologie Protection des vaisseaux spatiaux' ) / 10 )



/*

202 => 'Petit transporteur',

203 => 'Grand transporteur',

204 => 'Chasseur l&eacute;ger',

205 => 'Chasseur lourd',

206 => 'Croiseur',

207 => 'Vaisseau de bataille',

208 => 'Vaisseau de colonisation',

209 => 'Recycleur',

210 => 'Sonde espionnage',

211 => 'Bombardier',

212 => 'Satellite solaire',

213 => 'Destructeur',

214 => 'Etoile de la mort',

215 => 'Traqueur',



401 => 'Lanceur de missiles',

402 => 'Artillerie laser l&eacute;g&egrave;re',

403 => 'Artillerie laser lourde',

404 => 'Canon de Gauss',

405 => 'Artillerie &agrave; ions',

406 => 'Lanceur de plasma',

407 => 'Petit bouclier',

408 => 'Grand bouclier',



*/



$CombatCaps = array(

202 => array ( 'shield' =>    10, 'attack' =>      5, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1, 401 =>   1, 402 =>   1, 403 =>   1, 404 =>   1, 405 =>   1, 406 =>   1, 407 =>   1, 408 =>   1 )),

203 => array ( 'shield' =>    25, 'attack' =>      5, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1, 401 =>   1, 402 =>   1, 403 =>   1, 404 =>   1, 405 =>   1, 406 =>   1, 407 =>   1, 408 =>   1 )),

204 => array ( 'shield' =>    10, 'attack' =>     50, 'sd' => array (202 =>   2, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1, 401 =>   1, 402 =>   1, 403 =>   1, 404 =>   1, 405 =>   1, 406 =>   1, 407 =>   1, 408 =>   1 )),

205 => array ( 'shield' =>    25, 'attack' =>    150, 'sd' => array (202 =>   3, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1, 401 =>   1, 402 =>   1, 403 =>   1, 404 =>   1, 405 =>   1, 406 =>   1, 407 =>   1, 408 =>   1 )),

206 => array ( 'shield' =>    50, 'attack' =>    400, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   6, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1, 401 =>  10, 402 =>   1, 403 =>   1, 404 =>   1, 405 =>   1, 406 =>   1, 407 =>   1, 408 =>   1 )),

207 => array ( 'shield' =>   200, 'attack' =>   1000, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1, 401 =>   8, 402 =>   1, 403 =>   1, 404 =>   1, 405 =>   1, 406 =>   1, 407 =>   1, 408 =>   1 )),

208 => array ( 'shield' =>   100, 'attack' =>     50, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1, 401 =>   1, 402 =>   1, 403 =>   1, 404 =>   1, 405 =>   1, 406 =>   1, 407 =>   1, 408 =>   1 )),

209 => array ( 'shield' =>    10, 'attack' =>      1, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1, 401 =>   1, 402 =>   1, 403 =>   1, 404 =>   1, 405 =>   1, 406 =>   1, 407 =>   1, 408 =>   1 )),

210 => array ( 'shield' =>     0, 'attack' =>      0, 'sd' => array (202 =>   0, 203 =>   0, 204 =>   0, 205 =>   0, 206 =>   0, 207 =>   0, 208 =>   0, 209 =>   0, 210 =>    0, 211 =>   0, 212 =>    0, 213 =>   0, 214 =>   0, 215 =>   0, 401 =>   0, 402 =>   0, 403 =>   0, 404 =>   0, 405 =>   0, 406 =>   0, 407 =>   0, 408 =>   0 )),

211 => array ( 'shield' =>   500, 'attack' =>   1000, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1, 401 =>  20, 402 =>  20, 403 =>  10, 404 =>   1, 405 =>  10, 406 =>   1, 407 =>   1, 408 =>   1 )),

212 => array ( 'shield' =>    10, 'attack' =>      1, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    1, 211 =>   1, 212 =>    0, 213 =>   1, 214 =>   1, 215 =>   1, 401 =>   1, 402 =>   1, 403 =>   1, 404 =>   1, 405 =>   1, 406 =>   1, 407 =>   1, 408 =>   1 )),

213 => array ( 'shield' =>   500, 'attack' =>   2000, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   2, 401 =>   1, 402 =>  10, 403 =>   1, 404 =>   1, 405 =>   1, 406 =>   1, 407 =>   1, 408 =>   1 )),

214 => array ( 'shield' => 50000, 'attack' => 200000, 'sd' => array (202 => 250, 203 => 250, 204 => 200, 205 => 100, 206 =>  33, 207 =>  30, 208 => 250, 209 => 250, 210 => 1250, 211 =>  25, 212 => 1250, 213 =>   5, 214 =>   1, 215 =>  15, 401 => 200, 402 => 200, 403 => 100, 404 =>  50, 405 => 100, 406 =>   1, 407 =>   1, 408 =>   1 )),

215 => array ( 'shield' =>   400, 'attack' =>    700, 'sd' => array (202 =>   3, 203 =>   3, 204 =>   1, 205 =>   4, 206 =>   4, 207 =>   7, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1, 401 =>   1, 402 =>   1, 403 =>   1, 404 =>   1, 405 =>   1, 406 =>   1, 407 =>   1, 408 =>   1 )),



401 => array ( 'shield' =>    20, 'attack' =>     80, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1) ),

402 => array ( 'shield' =>    25, 'attack' =>    100, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1) ),

403 => array ( 'shield' =>   100, 'attack' =>    250, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1) ),

404 => array ( 'shield' =>   200, 'attack' =>   1100, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1) ),

405 => array ( 'shield' =>   500, 'attack' =>    150, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1) ),

406 => array ( 'shield' =>   300, 'attack' =>   3000, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1) ),

407 => array ( 'shield' =>  2000, 'attack' =>      1, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1) ),

408 => array ( 'shield' =>  2000, 'attack' =>      1, 'sd' => array (202 =>   1, 203 =>   1, 204 =>   1, 205 =>   1, 206 =>   1, 207 =>   1, 208 =>   1, 209 =>   1, 210 =>    5, 211 =>   1, 212 =>    5, 213 =>   1, 214 =>   1, 215 =>   1) ),



502 => array ( 'shield' =>     1, 'attack' =>      1 ),

503 => array ( 'shield' =>     1, 'attack' =>  12000 )

);



$AtFleet = array ( 203 => 2 );

$AtTechn = array ( 109 => 3, 110 => 5, 111 => 3 );

$AtCount = 1;



$DfFleet = array ( 402 => 9 );

$DfTechn = array ( 109 => 7, 110 => 7, 111 => 5 );

$DfCount = 1;





// Données en entrée :

// $AttackFleet -> array de tableaux des flottes attaquantes

// $AttackTech  -> array de tableaux des technologies des attaquants ainsi que leur id

// $AttackCount -> Nbre d'attaquants  ( de 1 a 5 )

// $TargetFleet -> array de tableaux des flottes defenseurs

// $TargetTech  -> array de tableaux des technologies des defenseurs ainsi que leur id

// $TargetCount -> Nbre de defenseurs ( de 1 a 5 )

//

function FleetCombat ( $AttackFleet, $AttackTech, $AttackCount, $TargetFleet, $TargetTech, $TargetCount ) {



}



function GetWeaponsPerType ( $TypeArray, $Tech ) {

	global $capacity;

	// Calcul de la force d'Attaque

	if (!is_null($TypeArray)) {

		foreach($TypeArray as $Type => $Count) {

			$Attack[$Type]      = round ($capacity[$Type]['attack'] + (($capacity[$Type]['attack'] * $Tech['109']) / 10));

			$Units['attack']   += $Count * $Attack[$Type];

		}

	}



}



function GetShiedsPerType ( $TypeArray, $Tech ) {

	global $capacity;

	// Calcul des points de Bouclier

	if (!is_null($TypeArray)) {

		foreach($TypeArray as $Type => $Count) {

			$Shield[$Type]      = round ($capacity[$Type]['shield'] + (($capacity[$Type]['shield'] * $Tech['110']) / 10));

			$Units['shield']   += $Count * $Shield[$Type];

		}

	}



}



function GetHullPerType ( $TypeArray, $Tech ) {

	global $pricelist;

	// Calcul des points de Coque

	if (!is_null($TypeArray)) {

		$Units['metal']     = 0;

		$Units['crystal']   = 0;

		$Units['deuterium'] = 0;

		foreach($TypeArray as $Type => $Count) {

			$Hull[$Type]         = ($pricelist[$Type]['metal'] + $pricelist[$Type]['crystal']) + ((($pricelist[$Type]['metal'] + $pricelist[$Type]['crystal']) * $Tech['111']) / 10);

			$Units['metal']     += $Count * $pricelist[$Type]['metal'];

			$Units['crystal']   += $Count * $pricelist[$Type]['crystal'];

			$Units['deuterium'] += $Count * $pricelist[$Type]['deuterium'];

		}

	}



}



?>
Por otro lado, se me ha ocurrido un modo de "visualizar" lo que digo que hago sin pasar el JS.

Tengo que hacer unas pruebas, pero se trataria de los siguiente.

1- Visualizar el universo completo (actualizable como he propuesto desde un principio).

Como se puede suponer, se podria pensar que es una bd privada, para evitar ese error y demostrar que esta vinculada (como cliente, no directamente) a la bd del juego.
- Enviais sondas a quien querais de manera que os asegureis que se crean escombros ( ya que no hay otro medio mas rapido para realizar cambios en la bd del juego , aunque si existen otros como colonizaciones o trasladar planetas pero son mas lentos). Tambien simplemente podeis cambiar nombres a los planetas.
-Entoces vereis, en primer lugar los escombros en vuestro ogarena , al igual que yo, salvo que la diferencia es que yo no tengo ni idea de a donde los creais, por eso lo vereis primero.
- Cuando mi JS lea esa posicion de las 684 paginas posibles, que tardara unos segundos (sobre unos 100 ms por pagina, 68 segundos) actualizara una pagina publica que dare a conocer en su momento. El hostin de esa pagina (el server) solo admite html.

Te sirve ¿como demostracion?

Un saludo

asturcon3
Site Admin
Site Admin
Mensajes: 6125
Registrado: 12 Nov 2007 14:36
Alianza: aSACo, ofcourse

Re: Motor de batallas, código fuente (muy técnico me temo)

Mensaje por asturcon3 » 03 Ene 2011 19:30

Te sirve ¿como demostracion?
¿Demostración de qué?

Eso es una parte del motor de batallas de xnova, no se qué pretendes decir con eso.

http://www.gforum.eu/index.php?showtopi ... ntry162628

ogArena no tiene el motor, ni el juego, programados en php.
Imagen

Andurino
Mensajes: 67
Registrado: 18 Dic 2008 05:22

Re: Motor de batallas, código fuente (muy técnico me temo)

Mensaje por Andurino » 03 Ene 2011 19:43

Imagen

Haber si te aclara algo el esquema.

Tus conexiones son sincronas. PETICION->RESPUESTA.
Tambien las conexiones de [CUALQUIERA]->[SERVIDORES-EXTERNOS] , lo digo porque la flecha es bidireccional lo cual es un error.
Y por no ser menos las conexiones [ASTURCOM]->[DB]

Yo tengo mantengo el estado permanentemente del site. PETICION<->RESPUESTA

Ademas, usare para las imagenes un sistema similar al que usas, pero con verificacion de contenido.
Tu supones que en un skin concreto existen todas las imagenes yo sin cargalas verifico su existencia como nombre de fichero, luego como fichero existente , aun asi el fichero puede estar corrupto o con la extension cambiada. Ahora indico que lea el archivo.
Los 68 segundos que como minimo calculo para actualizar toda EL UNIVERSO (que es el Ejemplo que te propongo a que autorices), es debido a que yo no tengo la bd (ni la quiero), simplemente no tengo acceso a ella para hacer los objetos de consulta apropiados. Ademas te crea una carga de trafico de 4K X 684 peticiones continuas, podia ser mas perro y hacer 684 peticiones en el mismo segundo que te generaria una carga de 2736 k. Lo cual dejaria tu conexion de subida algo tocada. Creo que lo mejor va ser que durante 10 min se puedan visualizar 5 Sistemas completos aleatorios 4k x 5 = 20k , y la velocidad de actualizacion seria de 500 ms, 0,5 segundos a lo que hay que sumarle otros traficos externos + sus tiempos de respuesta. Durante ese tiempo enviar sondas para crear escombros, vereis como se actualiza rapidamente sin recargar.

Por este motivo te solicite (no me acuerdo el orden ni importa):

A- una sintaxis de las variables th, tc
B- Un fichero de acceso global de lectura unica.
C- Colaboracion de algun tipo

Con el proposito de evitar retardos, traficos de red y otras lindezas totalmente INNECESARIAS.

Un saludo.

PD: Abajo a la dr (hacia el centro) ves varios dispositivos significativamente distintos , eso siginifica que podran jugar a ogarena con las mismas condicones. Ademas falta una cosa en esa imagen , que son las alianzas con utilidad.

Podrás erroneaneamente concluir que se quiere de algún modo hacer un juego paralelo , o exclusion de algun tipo . Es un error , solo es un esquema de lo QUE SE PUEDE HACER y que es distinto a la finalidad de mis solicitudes. IGUS propios, igualdad entre multisistemas y jugadores. evitar el uso malintencionado de scripts, etcc...

PD-2: El simulador de batalla o cualquier otra cosa que plantes o te planten , siempre tendra la misma incognita ¿de donde saco los datos para hacer los calculos ? Tu modelo es sincrono, unicamente otro modelo sincrono puede hacer frente a esas soluciones, lo que direccionas conscientemente a crear entornos pseudo-dinamicos , a base de leer y releer ya sea de forma automatica o manual, ya que requiere por ejemplo los informes de espionajes que has de copiar para pegar en el simulador. Operaciones de lectura que son evitables e innecesarias. Ah por cierto que sea dinamico != automatico (boot) ya que son los metodos del servidor web (en mi caso) los que evitan usos inapropiados o mejor dicho, solo permiten hacer las cosas como establecen las normas (que son bastante ambiguas, por razones obvias). Para tener ademas todos los datos leidos guardados en local (si quieres, <<te conviene>>) actualizando o creando dinamicamente los datos en local.

De este modo, puedes <<pensar>>, <<revisar>>, <<analizar>> o lo que te de la gana con los datos que ya has leido, y por supuesto cuando hay barritas podras <<pensar, analizar, revisar>> que hacer inmediatamente cuando el servidor se reactibe o indicarle al servidor que una construccion o investigacion no debia haber finalizado y lo ha hecho por las // que afecta a los jugadores, pero no suelen ser los causantes de ese estado. Las // son una idea genial aunque puede ser mejor.

Responder