]> git.llucax.com Git - z.facultad/75.07/algowars.git/blob - src/modelo/ov/naves/NavesEnemigas.pas
Import inicial después del "/var incident". :(
[z.facultad/75.07/algowars.git] / src / modelo / ov / naves / NavesEnemigas.pas
1 {** Distintos tipos de Naves Enemigas<br>\r
2     <i>Cambios:</i>\r
3     <PRE>\r
4     27/11/00: Se realizan algunos cambios para adaptarse a la nueva implementacion de cNave con disparos.\r
5     01/12/00: Se cambiaron las dimensiones de la nave para que los disparos sean mas "jugables".\r
6               Se cambia el orden de los argumentos de mDisparar para aprovechar los argumentos por defecto.\r
7     </PRE>}\r
8 unit NavesEnemigas;\r
9 \r
10 interface\r
11 \r
12 uses\r
13   Tipos,\r
14   Vectores,\r
15   Nave,\r
16   NaveEnemiga,\r
17   NavePropia,\r
18   ObjetoVolador,\r
19   Armas;\r
20 \r
21 type\r
22   {** Es una nave con misiles y lasers (igual que la propia)\r
23       que se desplaza por el epacio hasta que encuentra una nave propia para atacar.<br>\r
24       <u>Características:</u>\r
25       <PRE>\r
26       Dimensión:            25        metros\r
27       Potencia:             2         Cantidad de daño que hace por intervalo de tiempo\r
28       Energía:              100       Cantidad de daño que soporta antes de ser destruída\r
29       Velocidad máxima:     0,17      metros/milisegundos (612 km/h)\r
30       Campo de radar:       5000      metros (5 km)\r
31       Misiles:              5\r
32       Misiles Dirigidos:    2\r
33       </PRE>}\r
34   cNavePesada = class( cNaveEnemiga )\r
35     private\r
36       aCampoMinimo: tLongitud; // Distancia minima a la nave propia\r
37     public\r
38       {** Constructor}\r
39       constructor create( pos : cVector = nil; vel : cVector = nil );\r
40       {** Método heredado que hace que la nave reaccione ante la presencia\r
41           de la nave propia (en este caso la atacará con lasers y misiles)}\r
42       procedure mReaccionar( np : cNavePropia );override;\r
43       {** Método heredado, se sobreescribe porque se dibuja de forma distinta}\r
44       function mDibujar: tObjetosVoladores; override;\r
45       // SERIALIZACION\r
46       {** Devuelve una cadena de texto con el objeto serializado.}\r
47       function mSerializar: string; override;\r
48       {** Recrea el objeto a partir de una cadena de texto con el objeto\r
49           serializado.}\r
50       procedure mDesSerializar( str: string ); override;\r
51   end;\r
52 \r
53   {** Es una nave sin misiles, solo con lasers que\r
54       se desplaza por el epacio hasta que encuentra una nave propia para atacar.<br>\r
55       <u>Características:</u>\r
56       <PRE>\r
57       Dimensión:            15        metros\r
58       Potencia:             1         Cantidad de daño que hace por intervalo de tiempo\r
59       Energía:              60        Cantidad de daño que soporta antes de ser destruída\r
60       Velocidad máxima:     0,18      metros/milisegundos (648 km/h)\r
61       Campo de radar:       3000      metros (3 km)\r
62       Misiles:              0\r
63       Misiles Dirigidos:    0\r
64       </PRE>}\r
65   cNaveLiviana = class( cNaveEnemiga )\r
66     private\r
67       aCampoMinimo: tLongitud; // Distancia minima a la nave propia\r
68     public\r
69       {** Constructor}\r
70       constructor create( pos : cVector = nil; vel : cVector = nil );\r
71       {** Método heredado que hace que la nave reaccione ante la presencia\r
72           de la nave propia (en este caso la atacará con lasers)}\r
73       procedure mReaccionar( np : cNavePropia );override;\r
74       {** Método heredado, se sobreescribe porque se dibuja de forma distinta}\r
75       function mDibujar: tObjetosVoladores; override;\r
76       // SERIALIZACION\r
77       {** Devuelve una cadena de texto con el objeto serializado.}\r
78       function mSerializar: string; override;\r
79       {** Recrea el objeto a partir de una cadena de texto con el objeto\r
80           serializado.}\r
81       procedure mDesSerializar( str: string ); override;\r
82   end;\r
83 \r
84   {** Es una nave sin armas que se desplaza por el epacio\r
85       hasta que encuentra una nave propia, en ese momento empieza a huir avisando a\r
86       las demas naves enemigas la ultima posicion de la nave propia.<br>\r
87       <u>Características:</u>\r
88       <PRE>\r
89       Dimensión:            10        metros\r
90       Potencia:             1         Cantidad de daño que hace por intervalo de tiempo\r
91       Energía:              30        Cantidad de daño que soporta antes de ser destruída\r
92       Velocidad máxima:     0,2       metros/milisegundos (720 km/h)\r
93       Campo de radar:       2000      metros (2 km)\r
94       Misiles:              0\r
95       Misiles Dirigidos:    0\r
96       </PRE>}\r
97   cNaveEspia = class( cNaveEnemiga )\r
98     private\r
99       aPosicionEnemiga: cVector; // Indica la posicion de la nave propia. Si todavía no\r
100                                  //  la encontró, su valor es nil\r
101     protected\r
102       {** Método heredado se modifica porque su forma de modificar la velocidad es diferente al\r
103           resto de las naves enemigas}\r
104       procedure mModificarVelocidad( np: cNavePropia; modulo: tLongitud = -1 ); override;\r
105     public\r
106       {** Constructor }\r
107       constructor create( pos : cVector = nil; vel : cVector = nil );\r
108       {** Método que indica si está avisando }\r
109       function mAvisando: boolean;\r
110       {** Método que devuelve la última posición en dónde vió a la nave propia (si está avisando)}\r
111       function mGetPosicionEnemiga: cVector;\r
112       {** Método heredado que hace que la nave reaccione ante la presencia\r
113           de la nave propia (en este caso huirá y empezará a avisar al resto de las naves que encuentre\r
114           sobre la última posición de la nave propia)}\r
115       procedure mReaccionar( np : cNavePropia );override;\r
116       {** Destructor}\r
117       destructor destroy; override;\r
118       {** Método heredado, se sobreescribe porque esta nave en particular no puede disparar}\r
119       function mDisparar( dT: tTiempo; ov : cObjetoVolador = nil ): cArma; override;\r
120       {** Método heredado, se sobreescribe porque se dibuja de forma distinta}\r
121       function mDibujar: tObjetosVoladores; override;\r
122       // SERIALIZACION\r
123       {** Devuelve una cadena de texto con el objeto serializado.}\r
124       function mSerializar: string; override;\r
125       {** Recrea el objeto a partir de una cadena de texto con el objeto\r
126           serializado.}\r
127       procedure mDesSerializar( str: string ); override;\r
128   end;\r
129 \r
130   {** Es una nave sin armas que se desplaza por el epacio\r
131       hasta que encuentra una nave propia y trata de chocarla.<br>\r
132       <u>Características:</u>\r
133       <PRE>\r
134       Dimensión:            10        metros\r
135       Potencia:             4         Cantidad de daño que hace por intervalo de tiempo\r
136       Energía:              30        Cantidad de daño que soporta antes de ser destruída\r
137       Velocidad máxima:     0,2       metros/milisegundos (720 km/h)\r
138       Campo de radar:       2500      metros (2,5 km)\r
139       Misiles:              0\r
140       Misiles Dirigidos:    0\r
141       </PRE>}\r
142   cNaveSuicida = class( cNaveEnemiga )\r
143     public\r
144       {** Constructor}\r
145       constructor create( pos : cVector = nil; vel : cVector = nil );\r
146       {** Método heredado que hace que la nave reaccione ante la presencia\r
147           de la nave propia (en este caso tratará de chocarla)}\r
148       procedure mReaccionar( np : cNavePropia );override;\r
149       {** Método heredado, se sobreescribe porque esta nave en particular no puede disparar}\r
150       function mDisparar( dT: tTiempo; ov : cObjetoVolador = nil ): cArma; override;\r
151       {** Método heredado, se sobreescribe porque se dibuja de forma distinta}\r
152       function mDibujar: tObjetosVoladores; override;\r
153   end;\r
154 \r
155 implementation\r
156 \r
157 uses\r
158   RegExpr,\r
159   ObjetoPersistente,\r
160   Sysutils;\r
161 \r
162 { cNavePesada }\r
163 \r
164 {** Crea una instancia de una nave pesada.\r
165     @param pos Vector posición\r
166     @param vel Vector velocidad}\r
167 constructor cNavePesada.create(pos, vel: cVector);\r
168 begin\r
169   // La dimensión es 5 m de radio, la potencia 2, la energía 100, tiene 5 misiles comunes,\r
170   //  2 dirigidos, su velocidad maxima es 0,17 m/mseg (612 km/h) y su Campo de radar 5 km\r
171   inherited create( pos, vel, 25 {dim}, 2 {pot}, 100 {ene}, 5 {mis}, 2 {misdir},\r
172                     0.17 {velmax}, 5000 {rad});\r
173   aCampoMinimo := 500;\r
174 end;\r
175 \r
176 function cNavePesada.mDibujar: tObjetosVoladores;\r
177 begin\r
178   result := OV_NAVEPESADA;\r
179 end;\r
180 \r
181 {** Método heredado que hace que la nave reaccione ante la presencia\r
182     de la nave propia cerca (en este caso la atacará con lasers y misiles)\r
183     @param np Nave Propia con la cual esta reaccionando}\r
184 procedure cNavePesada.mReaccionar(np: cNavePropia);\r
185 var\r
186   modulo: tLongitud;\r
187 begin\r
188   modulo := mGetVelMax; // nuevo modulo de la velocidad igual a la velocidad maxima\r
189   if mGetDistancia( np ) < aCampoMinimo then // si esta cerca de la nave propia...\r
190     if np.mGetVelModulo < mGetVelMax then // si la vel de la nave propia es menor a la maxima\r
191       modulo := np.mGetVelModulo; // nuevo modulo de la velocidad igual al de la nave propia\r
192   mModificarVelocidad( np, modulo ); // cambiar la velocidad segun la nave propia y el nuevo modulo\r
193 end;\r
194 \r
195 {** Recrea el objeto a partir de una cadena de texto con el objeto\r
196     serializado.\r
197     @param str Cadena de texto con el objeto serializado.}\r
198 procedure cNavePesada.mDesSerializar(str: string);\r
199 var\r
200   r: TRegExpr;\r
201 begin\r
202   inherited mDesSerializar( str ); // SIEMPRE el ID debe ser el PRIMER atributo\r
203   r := TRegExpr.create;\r
204   // CAMPORADAR\r
205   try // se fija si hay errores al extraer los datos\r
206     r.Expression := '<campominimo>\s*([+\-]?\d+(\,\d+)?([eE][+\-]?\d+)?)\s*</campominimo>'; // contruye la expresion regular a buscar\r
207     if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...\r
208       aCampoMinimo := StrToFloat( r.Match[1] )\r
209     else // si no encontro la experesion...\r
210       raise ESerializacion.create( 'No se encontro el campo minimo' ); // cae en una excepcion\r
211   except // Si hubieron errores ...\r
212     on e: ERegExpr do begin // si fueron de expresiones regulares...\r
213       r.Free; // libera memoria\r
214       raise ESerializacion.create( ClassName + ': Error al extraer el campo minimo utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion\r
215     end;\r
216   end;\r
217   r.free;\r
218 end;\r
219 \r
220 {** Devuelve una cadena de texto con el objeto serializado.\r
221     @return Cadena de texto con el objeto serializado.}\r
222 function cNavePesada.mSerializar: string;\r
223 begin\r
224   result := inherited mSerializar +\r
225             '<campominimo>' + FloatToStrF( aCampoMinimo, ffGeneral, 18, 0 ) + '</campominimo>';\r
226 end;\r
227 \r
228 { cNaveLiviana }\r
229 \r
230 {** Crea una instancia de una nave liviana.\r
231     @param pos Vector posición\r
232     @param vel Vector velocidad}\r
233 constructor cNaveLiviana.create(pos, vel: cVector);\r
234 begin\r
235   // La dimensión es 3 m de radio, la potencia 1, la energía 60, no tiene misiles comunes\r
236   //  ni dirigidos, su velocidad maxima es 0,18 m/mseg (648 km/h) y su Campo de radar 3 km\r
237   // El retardo del laser es de .5 segundos, el del misil de 2 segundos y el del misil\r
238   //  dirigido de 5 segundos.\r
239   inherited create( pos, vel, 15 {dim}, 1 {pot}, 60 {ene}, 0 {mis}, 0 {misdir},\r
240                     0.18 {velmax}, 3000 {rad}, 500 {retlaser});\r
241   aCampoMinimo := 250;\r
242 end;\r
243 \r
244 {** Hace que se dispare un arma (todavía no está implementado)}\r
245 function cNaveLiviana.mDibujar: tObjetosVoladores;\r
246 begin\r
247   result := OV_NAVELIVIANA;\r
248 end;\r
249 \r
250 {** Método heredado que hace que la nave reaccione ante la presencia\r
251     de la nave propia (en este caso la atacará con lasers)\r
252     @param np Nave Propia con la cual esta reaccionando}\r
253 procedure cNaveLiviana.mReaccionar(np: cNavePropia);\r
254 var\r
255   modulo: tLongitud;\r
256 begin\r
257   modulo := mGetVelMax; // nuevo modulo de la velocidad igual a la velocidad maxima\r
258   if mGetDistancia( np ) < aCampoMinimo then // si esta cerca de la nave propia...\r
259     if np.mGetVelModulo < mGetVelMax then // si la vel de la nave propia es menor a la maxima\r
260       modulo := np.mGetVelModulo; // nuevo modulo de la velocidad igual al de la nave propia\r
261   mModificarVelocidad( np, modulo ); // cambiar la velocidad segun la nave propia y el nuevo modulo\r
262 end;\r
263 \r
264 {** Recrea el objeto a partir de una cadena de texto con el objeto\r
265     serializado.\r
266     @param str Cadena de texto con el objeto serializado.}\r
267 procedure cNaveLiviana.mDesSerializar(str: string);\r
268 var\r
269   r: TRegExpr;\r
270 begin\r
271   inherited mDesSerializar( str ); // SIEMPRE el ID debe ser el PRIMER atributo\r
272   r := TRegExpr.create;\r
273   // CAMPORADAR\r
274   try // se fija si hay errores al extraer los datos\r
275     r.Expression := '<campominimo>\s*([+\-]?\d+(\,\d+)?([eE][+\-]?\d+)?)\s*</campominimo>'; // contruye la expresion regular a buscar\r
276     if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...\r
277       aCampoMinimo := StrToFloat( r.Match[1] )\r
278     else // si no encontro la experesion...\r
279       raise ESerializacion.create( 'No se encontro el campo minimo' ); // cae en una excepcion\r
280   except // Si hubieron errores ...\r
281     on e: ERegExpr do begin // si fueron de expresiones regulares...\r
282       r.Free; // libera memoria\r
283       raise ESerializacion.create( ClassName + ': Error al extraer el campo minimo utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion\r
284     end;\r
285   end;\r
286   r.free;\r
287 end;\r
288 \r
289 {** Devuelve una cadena de texto con el objeto serializado.\r
290     @return Cadena de texto con el objeto serializado.}\r
291 function cNaveLiviana.mSerializar: string;\r
292 begin\r
293   result := inherited mSerializar +\r
294             '<campominimo>' + FloatToStrF( aCampoMinimo, ffGeneral, 18, 0 ) + '</campominimo>';\r
295 end;\r
296 \r
297 { cNaveEspia }\r
298 \r
299 {** Crea una instancia de una nave espía.\r
300     @param pos Vector posición\r
301     @param vel Vector velocidad}\r
302 constructor cNaveEspia.create(pos, vel: cVector);\r
303 begin\r
304   // La dimensión es 2 m de radio, la potencia 1, la energía 30, no tiene misiles comunes\r
305   //  ni dirigidos, su velocidad maxima es 0,2 m/mseg (720 km/h) y su Campo de radar 3 km\r
306   inherited create( pos, vel, 10 {dim}, 1 {pot}, 30 {ene}, 0 {mis}, 0 {misdir},\r
307                     0.2 {velmax}, 2000 {rad} );\r
308   aPosicionEnemiga := nil;\r
309 end;\r
310 \r
311 {** Destructor}\r
312 destructor cNaveEspia.destroy;\r
313 begin\r
314   aPosicionEnemiga.free;\r
315   inherited;\r
316 end;\r
317 \r
318 {** Hace que se dispare un arma\r
319     @param  ov Objetivo del disparo\r
320     @return Arma disparada (o <i>nil</i> si no se puede disparar ningún arma)}\r
321 function cNaveEspia.mDisparar( dT: tTiempo; ov : cObjetoVolador ): cArma;\r
322 begin\r
323   result := nil; // No puede disparar nada (nunca!)\r
324 end;\r
325 \r
326 {** Método que indica si está avisando\r
327     @return <i>true</i> si está avisando, <i>false</i> si no lo está}\r
328 function cNaveEspia.mAvisando: boolean;\r
329 begin\r
330   result := ( aPosicionEnemiga <> nil ); // True si la posicion no es nil\r
331 end;\r
332 \r
333 {** Método que devuelve la última posición en dónde vió a la nave propia (si está avisando)\r
334     @return Última posición donde detectó a la nave propia (<i>nil</i> si no la detecto nunca)}\r
335 function cNaveEspia.mDibujar: tObjetosVoladores;\r
336 begin\r
337   result := OV_NAVEESPIA;\r
338 end;\r
339 \r
340 function cNaveEspia.mGetPosicionEnemiga: cVector;\r
341 begin\r
342   result := cVector.create( aPosicionEnemiga );\r
343 end;\r
344 \r
345 {** Modifica la velocidad de la nave en base a la nave propia.\r
346     @param np     Nave propia con la cual se calculará la dirección de la nueva velocidad\r
347     @param modulo Nuevo módulo de la velocidad}\r
348 procedure cNaveEspia.mModificarVelocidad(np: cNavePropia; modulo: tLongitud);\r
349 var\r
350   pos,          // Vector temporal\r
351   vel: cVector; // Vector temporal\r
352 begin\r
353   pos := np.mGetPosicion;\r
354   vel := mGetPosicion.mRestar( pos ); // Crea un vector igual a su posicion\r
355                                       // Le resta la posicion de la nave propia\r
356   mSetVelModulo( mGetVelMax );        // Setea el modulo al maximo\r
357   mSetVelDir( vel );                  // Copia el vector a su velocidad\r
358   vel.free;                           // Libera el vector temporal\r
359   pos.free;                           // Libera el vector temporal\r
360 end;\r
361 \r
362 {** Método heredado que hace que la nave reaccione ante la presencia\r
363     de la nave propia (en este caso huirá y empezará a avisar al resto de las naves que encuentre\r
364     sobre la última posición de la nave propia)\r
365     @param np Nave Propia con la cual esta reaccionando}\r
366 procedure cNaveEspia.mReaccionar(np: cNavePropia);\r
367 begin\r
368   mModificarVelocidad( np );\r
369   // Si ya tiene una posición, la modifica, si no crea una nueva\r
370   if aPosicionEnemiga <> nil then\r
371     aPosicionEnemiga.free;\r
372   aPosicionEnemiga := np.mGetPosicion;\r
373 end;\r
374 \r
375 {** Recrea el objeto a partir de una cadena de texto con el objeto\r
376     serializado.\r
377     @param str Cadena de texto con el objeto serializado.}\r
378 procedure cNaveEspia.mDesSerializar(str: string);\r
379 var\r
380   r: TRegExpr;\r
381 begin\r
382   inherited mDesSerializar( str ); // SIEMPRE el ID debe ser el PRIMER atributo\r
383   r := TRegExpr.create;\r
384   // POSICIONENEMIGA\r
385   try // se fija si hay errores al extraer los datos\r
386     r.Expression := '<posicionenemiga>\s*(.+)\s*</posicionenemiga>'; // contruye la expresion regular a buscar\r
387     if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...\r
388       if r.Match[1] = 'nil' then begin // Si la posicion enemiga recuperada es nil...\r
389         aPosicionEnemiga.free;   // Libera la posicion actual\r
390         aPosicionEnemiga := nil; // y la pone en nil\r
391       end else // si es otra cosa, la interpreta\r
392         if aPosicionEnemiga <> nil then // Si no es nulo\r
393           aPosicionEnemiga.mDesSerializar( r.Match[1] ) // Lo deserializa\r
394         else // si es nulo\r
395           aPosicionEnemiga := cVector.crearDeSerializado( r.Match[1] ) // lo crea\r
396     else // si no encontro la experesion...\r
397       raise ESerializacion.create( 'No se encontro la posicion enemiga' ); // cae en una excepcion\r
398   except // Si hubieron errores ...\r
399     on e: ESerializacion do begin // Si fueron de serializacion...\r
400       r.Free; // libera memoria\r
401       raise ESerializacion.create( ClassName + ': Error al deserializar la posicion enemiga: ' + e.Message ); // cae en una excepcion\r
402     end;\r
403     on e: ERegExpr do begin // si fueron de expresiones regulares...\r
404       r.Free; // libera memoria\r
405       raise ESerializacion.create( ClassName + ': Error al extraer la posicion enemiga utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion\r
406     end;\r
407   end;\r
408   r.free;\r
409 end;\r
410 \r
411 {** Devuelve una cadena de texto con el objeto serializado.\r
412     @return Cadena de texto con el objeto serializado.}\r
413 function cNaveEspia.mSerializar: string;\r
414 var\r
415   posene: string;\r
416 begin\r
417   // Si el objetivo es nil o está destruido, se setea el atributo class del\r
418   // TAG objetivo como '0' y entre el TAG se indica que es nil. Si no se\r
419   // setea como el nombre de la clase y su expresion serializada respectivamente\r
420   posene := 'nil';\r
421   if aPosicionEnemiga <> nil then\r
422     posene := aPosicionEnemiga.mSerializar;\r
423   result := inherited mSerializar +\r
424             '<posicionenemiga>' + posene + '</posicionenemiga>';\r
425 end;\r
426 \r
427 { cNaveSuicida }\r
428 \r
429 {** Crea una instancia de una nave suicida.\r
430     @param pos Vector posición\r
431     @param vel Vector velocidad}\r
432 constructor cNaveSuicida.create(pos, vel: cVector);\r
433 begin\r
434   // La dimensión es 2 m de radio, la potencia 4, la energía 30, no tiene misiles comunes\r
435   //  ni dirigidos, su velocidad maxima es 0,2 m/mseg (720 km/h) y su Campo de radar 1 km\r
436   inherited create( pos, vel, 10 {dim}, 4 {pot}, 30 {ene}, 0 {mis}, 0 {misdir},\r
437                     0.2 {velmax}, 2500 {rad});\r
438 end;\r
439 \r
440 {** Método heredado que hace que la nave reaccione ante la presencia\r
441     de la nave propia (en este caso tratará de chocarla)\r
442     @param np Nave Propia con la cual esta reaccionando}\r
443 function cNaveSuicida.mDibujar: tObjetosVoladores;\r
444 begin\r
445   result := OV_NAVESUICIDA;\r
446 end;\r
447 \r
448 procedure cNaveSuicida.mReaccionar(np: cNavePropia);\r
449 begin\r
450   mModificarVelocidad( np );\r
451 end;\r
452 \r
453 {** Hace que se dispare un arma\r
454     @param  ov Objetivo del disparo\r
455     @return Arma disparada (o <i>nil</i> si no se puede disparar ningún arma)}\r
456 function cNaveSuicida.mDisparar( dT: tTiempo; ov : cObjetoVolador ): cArma;\r
457 begin\r
458   result := nil; // No puede disparar nada (nunca!)\r
459 end;\r
460 \r
461 end.\r