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);
}
}
}
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)
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)
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:...
...
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)
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;
}
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;
};