naev 0.12.6
tech.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
11#include "SDL_timer.h"
13
14#include "tech.h"
15
16#include "array.h"
17#include "commodity.h"
18#include "conf.h"
19#include "log.h"
20#include "ndata.h"
21#include "nxml.h"
22#include "outfit.h"
23#include "rng.h"
24#include "ship.h"
25
26#define XML_TECH_ID "Techs"
27#define XML_TECH_TAG "tech"
28
39
43typedef struct tech_item_s {
45 double chance;
46 union {
47 void *ptr;
48 const Outfit *outfit;
49 const Ship *ship;
50 const Commodity *comm;
51 int grp;
52 const tech_group_t *grpptr;
53 } u;
55
60 char *name;
61 char *filename;
63};
64
65/*
66 * Group list.
67 */
68static tech_group_t *tech_groups = NULL;
69
70/*
71 * Prototypes.
72 */
73static void tech_createMetaGroup( tech_group_t *grp, tech_group_t **tech,
74 int num );
75static void tech_freeGroup( tech_group_t *grp );
76static char *tech_getItemName( tech_item_t *item );
77/* Loading. */
78static tech_item_t *tech_itemGrow( tech_group_t *grp );
79static int tech_parseFile( tech_group_t *tech, const char *file );
80static int tech_parseFileData( tech_group_t *tech );
81static int tech_parseXMLData( tech_group_t *tech, xmlNodePtr parent );
82static tech_item_t *tech_addItemOutfit( tech_group_t *grp, const char *name );
83static tech_item_t *tech_addItemShip( tech_group_t *grp, const char *name );
84static tech_item_t *tech_addItemCommodity( tech_group_t *grp,
85 const char *name );
86static tech_item_t *tech_addItemTechInternal( tech_group_t *tech,
87 const char *value );
88static int tech_getID( const char *name );
89static int tech_addItemGroupPointer( tech_group_t *grp,
90 const tech_group_t *ptr );
91static tech_item_t *tech_addItemGroup( tech_group_t *grp, const char *name );
92/* Getting by tech. */
93static void **tech_addGroupItem( void **items, tech_item_type_t type,
94 const tech_group_t *tech );
95
96static int tech_cmp( const void *p1, const void *p2 )
97{
98 const tech_group_t *t1 = p1;
99 const tech_group_t *t2 = p2;
100 return strcmp( t1->name, t2->name );
101}
102
106int tech_load( void )
107{
108#if DEBUGGING
109 Uint32 time = SDL_GetTicks();
110#endif /* DEBUGGING */
111 int s;
112 char **tech_files = ndata_listRecursive( TECH_DATA_PATH );
113
114 /* Create the array. */
115 tech_groups = array_create( tech_group_t );
116
117 /* First pass create the groups - needed to reference them later. */
118 for ( int i = 0; i < array_size( tech_files ); i++ ) {
119 tech_group_t tech;
120 int ret;
121
122 if ( !ndata_matchExt( tech_files[i], "xml" ) )
123 continue;
124
125 ret = tech_parseFile( &tech, tech_files[i] );
126 if ( ret == 0 ) {
127 tech.filename = strdup( tech_files[i] );
128 array_push_back( &tech_groups, tech );
129 }
130
131 free( tech_files[i] );
132 }
133 array_free( tech_files );
134 array_shrink( &tech_groups );
135
136 /* Sort. */
137 qsort( tech_groups, array_size( tech_groups ), sizeof( tech_group_t ),
138 tech_cmp );
139
140 /* Now we load the data. */
141 s = array_size( tech_groups );
142 for ( int i = 0; i < s; i++ )
143 tech_parseFileData( &tech_groups[i] );
144
145 /* Info. */
146#if DEBUGGING
147 if ( conf.devmode ) {
148 DEBUG( n_( "Loaded %d tech group in %.3f s",
149 "Loaded %d tech groups in %.3f s", s ),
150 s, ( SDL_GetTicks() - time ) / 1000. );
151 } else
152 DEBUG( n_( "Loaded %d tech group", "Loaded %d tech groups", s ), s );
153#endif /* DEBUGGING */
154
155 return 0;
156}
157
161void tech_free( void )
162{
163 /* Free all individual techs. */
164 int s = array_size( tech_groups );
165 for ( int i = 0; i < s; i++ )
166 tech_freeGroup( &tech_groups[i] );
167
168 /* Free the tech array. */
169 array_free( tech_groups );
170}
171
175static void tech_freeGroup( tech_group_t *grp )
176{
177 free( grp->name );
178 free( grp->filename );
179 array_free( grp->items );
180}
181
185tech_group_t *tech_groupCreateXML( xmlNodePtr node )
186{
187 /* Load data. */
188 tech_group_t *tech = tech_groupCreate();
189 tech_parseXMLData( tech, node );
190 return tech;
191}
192
196tech_group_t *tech_groupCreate( void )
197{
198 tech_group_t *tech = calloc( 1, sizeof( tech_group_t ) );
199 return tech;
200}
201
205void tech_groupDestroy( tech_group_t *grp )
206{
207 if ( grp == NULL )
208 return;
209
210 tech_freeGroup( grp );
211 free( grp );
212}
213
217static char *tech_getItemName( tech_item_t *item )
218{
219 /* Handle type. */
220 switch ( item->type ) {
221 case TECH_TYPE_OUTFIT:
222 return item->u.outfit->name;
223 case TECH_TYPE_SHIP:
224 return item->u.ship->name;
226 return item->u.comm->name;
227 case TECH_TYPE_GROUP:
228 return tech_groups[item->u.grp].name;
230 return item->u.grpptr->name;
231 }
232
233 return NULL;
234}
235
239int tech_groupWrite( xmlTextWriterPtr writer, tech_group_t *grp )
240{
241 int s;
242
243 /* Handle empty groups. */
244 if ( grp == NULL )
245 return 0;
246
247 /* Node header. */
248 xmlw_startElem( writer, "tech" );
249
250 /* Save items. */
251 s = array_size( grp->items );
252 for ( int i = 0; i < s; i++ )
253 xmlw_elem( writer, "item", "%s", tech_getItemName( &grp->items[i] ) );
254
255 xmlw_endElem( writer ); /* "tech" */
256
257 return 0;
258}
259
263static int tech_parseFile( tech_group_t *tech, const char *file )
264{
265 xmlNodePtr parent;
266 xmlDocPtr doc = xml_parsePhysFS( file );
267 if ( doc == NULL )
268 return -1;
269
270 parent = doc->xmlChildrenNode; /* first faction node */
271 if ( parent == NULL ) {
272 WARN( _( "Malformed '%s' file: does not contain elements" ), file );
273 return -1;
274 }
275
276 /* Just in case. */
277 memset( tech, 0, sizeof( tech_group_t ) );
278
279 /* Get name. */
280 xmlr_attr_strd( parent, "name", tech->name );
281 if ( tech->name == NULL ) {
282 WARN( _( "tech node does not have 'name' attribute" ) );
283 return 1;
284 }
285
286 xmlFreeDoc( doc );
287
288 return 0;
289}
290
294static int tech_parseXMLData( tech_group_t *tech, xmlNodePtr parent )
295{
296 /* Parse the data. */
297 xmlNodePtr node = parent->xmlChildrenNode;
298 do {
299 xml_onlyNodes( node );
300 if ( xml_isNode( node, "item" ) ) {
301 char *buf, *name;
302 tech_item_t *itm;
303
304 /* Must have name. */
305 name = xml_get( node );
306 if ( name == NULL ) {
307 WARN( _( "Tech group '%s' has an item without a value." ),
308 tech->name );
309 continue;
310 }
311
312 /* Try to find hard-coded type. */
313 xmlr_attr_strd( node, "type", buf );
314 if ( buf == NULL ) {
315 itm = tech_addItemTechInternal( tech, name );
316 } else if ( strcmp( buf, "group" ) == 0 ) {
317 itm = tech_addItemGroup( tech, name );
318 WARN( _( "Group item '%s' not found in tech group '%s'." ), name,
319 tech->name );
320 } else if ( strcmp( buf, "outfit" ) == 0 ) {
321 itm = tech_addItemOutfit( tech, name );
322 WARN( _( "Outfit item '%s' not found in tech group '%s'." ), name,
323 tech->name );
324 } else if ( strcmp( buf, "ship" ) == 0 ) {
325 itm = tech_addItemShip( tech, name );
326 WARN( _( "Ship item '%s' not found in tech group '%s'." ), name,
327 tech->name );
328 } else if ( strcmp( buf, "commodity" ) == 0 ) {
329 itm = tech_addItemCommodity( tech, name );
330 if ( itm == NULL )
331 WARN( _( "Commodity item '%s' not found in tech group '%s'." ),
332 name, tech->name );
333 } else
334 itm = NULL;
335 xmlr_attr_float_def( node, "chance", itm->chance, -1. );
336 free( buf );
337 continue;
338 }
339 WARN( _( "Tech group '%s' has unknown node '%s'." ), tech->name,
340 node->name );
341 } while ( xml_nextNode( node ) );
342
343 return 0;
344}
345
349static int tech_parseFileData( tech_group_t *tech )
350{
351 xmlNodePtr parent;
352 const char *file = tech->filename;
353 xmlDocPtr doc = xml_parsePhysFS( file );
354 if ( doc == NULL )
355 return -1;
356
357 parent = doc->xmlChildrenNode; /* first faction node */
358 if ( parent == NULL ) {
359 WARN( _( "Malformed '%s' file: does not contain elements" ), file );
360 return -1;
361 }
362
363 /* Parse the data. */
364 tech_parseXMLData( tech, parent );
365
366 xmlFreeDoc( doc );
367
368 return 0;
369}
370
374static tech_item_t *tech_itemGrow( tech_group_t *grp )
375{
376 if ( grp->items == NULL )
377 grp->items = array_create( tech_item_t );
378 tech_item_t *itm = &array_grow( &grp->items );
379 memset( itm, 0, sizeof( tech_item_t ) );
380 return itm;
381}
382
383static tech_item_t *tech_addItemOutfit( tech_group_t *grp, const char *name )
384{
385 tech_item_t *item;
386 const Outfit *o;
387
388 /* Get the outfit. */
389 o = outfit_getW( name );
390 if ( o == NULL )
391 return NULL;
392
393 /* Load the new item. */
394 item = tech_itemGrow( grp );
395 item->type = TECH_TYPE_OUTFIT;
396 item->u.outfit = o;
397 return item;
398}
399
403static tech_item_t *tech_addItemShip( tech_group_t *grp, const char *name )
404{
405 tech_item_t *item;
406 const Ship *s;
407
408 /* Get the outfit. */
409 s = ship_getW( name );
410 if ( s == NULL )
411 return NULL;
412
413 /* Load the new item. */
414 item = tech_itemGrow( grp );
415 item->type = TECH_TYPE_SHIP;
416 item->u.ship = s;
417 return item;
418}
419
423static tech_item_t *tech_addItemCommodity( tech_group_t *grp, const char *name )
424{
425 tech_item_t *item;
426 Commodity *c;
427
428 /* Get the outfit. */
429 c = commodity_getW( name );
430 if ( c == NULL )
431 return NULL;
432
433 /* Load the new item. */
434 item = tech_itemGrow( grp );
436 item->u.comm = c;
437 return item;
438}
439
443int tech_addItem( const char *name, const char *value )
444{
445 int id;
446 tech_group_t *tech;
447 tech_item_t *ret;
448
449 /* Get ID. */
450 id = tech_getID( name );
451 if ( id < 0 ) {
452 WARN( _( "Trying to add item '%s' to non-existent tech '%s'." ), value,
453 name );
454 return -1;
455 }
456
457 /* Comfort. */
458 tech = &tech_groups[id];
459
460 /* Try to add the tech. */
461 ret = tech_addItemGroup( tech, value );
462 if ( ret == NULL )
463 ret = tech_addItemOutfit( tech, value );
464 if ( ret == NULL )
465 ret = tech_addItemShip( tech, value );
466 if ( ret == NULL )
467 ret = tech_addItemCommodity( tech, value );
468 if ( ret == NULL ) {
469 WARN( _( "Generic item '%s' not found in tech group '%s'" ), value,
470 name );
471 return -1;
472 }
473
474 return 0;
475}
476
480int tech_addItemTech( tech_group_t *tech, const char *value )
481{
482 return ( tech_addItemTechInternal( tech, value ) != NULL );
483}
484
485static tech_item_t *tech_addItemTechInternal( tech_group_t *tech,
486 const char *value )
487{
488 /* Try to add the tech. */
489 tech_item_t *ret = tech_addItemGroup( tech, value );
490 if ( ret == NULL )
491 ret = tech_addItemOutfit( tech, value );
492 if ( ret == NULL )
493 ret = tech_addItemShip( tech, value );
494 if ( ret == NULL )
495 ret = tech_addItemCommodity( tech, value );
496 if ( ret == NULL ) {
497 WARN( _( "Generic item '%s' not found in tech group" ), value );
498 return NULL;
499 }
500 return ret;
501}
502
506int tech_rmItemTech( tech_group_t *tech, const char *value )
507{
508 /* Iterate over to find it. */
509 int s = array_size( tech->items );
510 for ( int i = 0; i < s; i++ ) {
511 const char *buf = tech_getItemName( &tech->items[i] );
512 if ( strcmp( buf, value ) == 0 ) {
513 array_erase( &tech->items, &tech->items[i], &tech->items[i + 1] );
514 return 0;
515 }
516 }
517
518 WARN( _( "Item '%s' not found in tech group" ), value );
519 return -1;
520}
521
525int tech_rmItem( const char *name, const char *value )
526{
527 int id, s;
528 tech_group_t *tech;
529
530 /* Get ID. */
531 id = tech_getID( name );
532 if ( id < 0 ) {
533 WARN( _( "Trying to remove item '%s' to non-existent tech '%s'." ), value,
534 name );
535 return -1;
536 }
537
538 /* Comfort. */
539 tech = &tech_groups[id];
540
541 /* Iterate over to find it. */
542 s = array_size( tech->items );
543 for ( int i = 0; i < s; i++ ) {
544 const char *buf = tech_getItemName( &tech->items[i] );
545 if ( strcmp( buf, value ) == 0 ) {
546 array_erase( &tech->items, &tech->items[i], &tech->items[i + 1] );
547 return 0;
548 }
549 }
550
551 WARN( _( "Item '%s' not found in tech group '%s'" ), value, name );
552 return -1;
553}
554
558static int tech_getID( const char *name )
559{
560 const tech_group_t q = { .name = (char *)name };
561 const tech_group_t *t = bsearch( &q, tech_groups, array_size( tech_groups ),
562 sizeof( tech_group_t ), tech_cmp );
563 if ( t == NULL )
564 return -1L;
565 return t - tech_groups;
566}
567
571static int tech_addItemGroupPointer( tech_group_t *grp,
572 const tech_group_t *ptr )
573{
574 /* Load the new item. */
575 tech_item_t *item = tech_itemGrow( grp );
577 item->u.grpptr = ptr;
578 return 0;
579}
580
584static tech_item_t *tech_addItemGroup( tech_group_t *grp, const char *name )
585{
586 tech_item_t *item;
587 int tech;
588
589 /* Try to find the tech. */
590 tech = tech_getID( name );
591 if ( tech < 0 )
592 return NULL;
593
594 /* Load the new item. */
595 item = tech_itemGrow( grp );
596 item->type = TECH_TYPE_GROUP;
597 item->u.grp = tech;
598 return item;
599}
600
608static void tech_createMetaGroup( tech_group_t *grp, tech_group_t **tech,
609 int num )
610{
611 /* Create meta group. */
612 memset( grp, 0, sizeof( tech_group_t ) );
613
614 /* Create a meta-group. */
615 for ( int i = 0; i < num; i++ )
616 tech_addItemGroupPointer( grp, tech[i] );
617}
618
623static void **tech_addGroupItem( void **items, tech_item_type_t type,
624 const tech_group_t *tech )
625{
626 /* Set up. */
627 int size = array_size( tech->items );
628
629 /* Handle specified type. */
630 for ( int i = 0; i < size; i++ ) {
631 int f;
632 tech_item_t *item = &tech->items[i];
633
634 /* Only care about type. */
635 if ( item->type != type )
636 continue;
637
638 /* Skip if already in list. */
639 f = 0;
640 for ( int j = 0; j < array_size( items ); j++ ) {
641 if ( items[j] == item->u.ptr ) {
642 f = 1;
643 break;
644 }
645 }
646 if ( f == 1 )
647 continue;
648
649 /* Check chance. */
650 if ( ( item->chance > 0. ) && ( RNGF() < item->chance ) )
651 continue;
652
653 /* Add. */
654 if ( items == NULL )
655 items = array_create( void * );
656 array_push_back( &items, item->u.ptr );
657 }
658
659 /* Now handle other groups. */
660 for ( int i = 0; i < size; i++ ) {
661 tech_item_t *item = &tech->items[i];
662
663 /* Only handle commodities for now. */
664 if ( item->type == TECH_TYPE_GROUP )
665 items = tech_addGroupItem( items, type, &tech_groups[item->u.grp] );
666 else if ( item->type == TECH_TYPE_GROUP_POINTER )
667 items = tech_addGroupItem( items, type, item->u.grpptr );
668 }
669
670 return items;
671}
672
680int tech_hasItem( const tech_group_t *tech, const char *item )
681{
682 if ( tech == NULL )
683 return 0;
684 int s = array_size( tech->items );
685 for ( int i = 0; i < s; i++ ) {
686 const char *buf = tech_getItemName( &tech->items[i] );
687 if ( strcmp( buf, item ) == 0 )
688 return 1;
689 }
690 return 0;
691}
692
693static int tech_hasItemInternal( const tech_group_t *tech,
694 const tech_item_t *item )
695{
696 if ( tech == NULL )
697 return 0;
698 int s = array_size( tech->items );
699 for ( int i = 0; i < s; i++ ) {
700 const tech_item_t *itemi = &tech->items[i];
701
702 if ( item->type == itemi->type ) {
703 switch ( item->type ) {
704 case TECH_TYPE_OUTFIT:
705 if ( item->u.outfit == itemi->u.outfit )
706 return 1;
707 break;
708 case TECH_TYPE_SHIP:
709 if ( item->u.ship == itemi->u.ship )
710 return 1;
711 break;
713 if ( item->u.comm == itemi->u.comm )
714 return 1;
715 break;
716 default:
717 break;
718 }
719 }
720
721 if ( itemi->type == TECH_TYPE_GROUP ) {
722 if ( tech_hasItemInternal( &tech_groups[itemi->u.grp], item ) )
723 return 1;
724 } else if ( itemi->type == TECH_TYPE_GROUP_POINTER ) {
725 if ( tech_hasItemInternal( itemi->u.grpptr, item ) )
726 return 1;
727 }
728 }
729 return 0;
730}
731
739int tech_hasShip( const tech_group_t *tech, const Ship *ship )
740{
741 const tech_item_t item = {
742 .type = TECH_TYPE_SHIP,
743 .u.ship = ship,
744 };
745 return tech_hasItemInternal( tech, &item );
746}
747
755int tech_hasOutfit( const tech_group_t *tech, const Outfit *outfit )
756{
757 const tech_item_t item = {
758 .type = TECH_TYPE_OUTFIT,
759 .u.outfit = outfit,
760 };
761 return tech_hasItemInternal( tech, &item );
762}
763
771int tech_hasCommodity( const tech_group_t *tech, const Commodity *comm )
772{
773 const tech_item_t item = {
774 .type = TECH_TYPE_COMMODITY,
775 .u.comm = comm,
776 };
777 return tech_hasItemInternal( tech, &item );
778}
779
785int tech_getItemCount( const tech_group_t *tech )
786{
787 return array_size( tech->items );
788}
789
797char **tech_getItemNames( const tech_group_t *tech, int *n )
798{
799 int s;
800 char **names;
801
802 *n = s = array_size( tech->items );
803 names = malloc( sizeof( char *) * s );
804
805 for ( int i = 0; i < s; i++ )
806 names[i] = strdup( tech_getItemName( &tech->items[i] ) );
807
808 return names;
809}
810
817char **tech_getAllItemNames( int *n )
818{
819 int s;
820 char **names;
821
822 *n = s = array_size( tech_groups );
823 names = malloc( sizeof( char *) * s );
824
825 for ( int i = 0; i < s; i++ )
826 names[i] = strdup( tech_groups[i].name );
827
828 return names;
829}
830
839Outfit **tech_getOutfit( const tech_group_t *tech )
840{
841 Outfit **o;
842
843 if ( tech == NULL )
844 return NULL;
845
846 o = (Outfit **)tech_addGroupItem( NULL, TECH_TYPE_OUTFIT, tech );
847
848 /* Sort. */
849 if ( o != NULL )
850 qsort( o, array_size( o ), sizeof( Outfit * ), outfit_compareTech );
851
852 return o;
853}
854
864Outfit **tech_getOutfitArray( tech_group_t **tech, int num )
865{
866 tech_group_t grp;
867 Outfit **o;
868
869 if ( tech == NULL )
870 return NULL;
871
872 tech_createMetaGroup( &grp, tech, num );
873 o = tech_getOutfit( &grp );
874 tech_freeGroup( &grp );
875
876 return o;
877}
878
887Ship **tech_getShip( const tech_group_t *tech )
888{
889 Ship **s;
890
891 if ( tech == NULL )
892 return NULL;
893
894 /* Get the outfits. */
895 s = (Ship **)tech_addGroupItem( NULL, TECH_TYPE_SHIP, tech );
896
897 /* Sort. */
898 if ( s != NULL )
899 qsort( s, array_size( s ), sizeof( Ship * ), ship_compareTech );
900
901 return s;
902}
903
913Ship **tech_getShipArray( tech_group_t **tech, int num )
914{
915 tech_group_t grp;
916 Ship **s;
917
918 if ( tech == NULL )
919 return NULL;
920
921 tech_createMetaGroup( &grp, tech, num );
922 s = tech_getShip( &grp );
923 tech_freeGroup( &grp );
924
925 return s;
926}
927
937Commodity **tech_getCommodityArray( tech_group_t **tech, int num )
938{
939 tech_group_t grp;
940 Commodity **c;
941
942 if ( tech == NULL )
943 return NULL;
944
945 tech_createMetaGroup( &grp, tech, num );
946 c = tech_getCommodity( &grp );
947 tech_freeGroup( &grp );
948
949 return c;
950}
951
960Commodity **tech_getCommodity( const tech_group_t *tech )
961{
962 Commodity **c;
963
964 if ( tech == NULL )
965 return NULL;
966
967 /* Get the commodities. */
969
970 /* Sort. */
971 if ( c != NULL )
972 qsort( c, array_size( c ), sizeof( Commodity * ), commodity_compareTech );
973
974 return c;
975}
976
980int tech_checkOutfit( const tech_group_t *tech, const Outfit *o )
981{
982 Outfit **to = tech_getOutfit( tech );
983 for ( int i = 0; i < array_size( to ); i++ ) {
984 if ( to[i] == o ) {
985 array_free( to );
986 return 1;
987 }
988 }
989 array_free( to );
990 return 0;
991}
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
Definition array.h:170
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
Definition array.h:148
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:179
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
Definition array.h:122
#define array_shrink(ptr_array)
Shrinks memory to fit only ‘size’ elements.
Definition array.h:160
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
Definition array.h:134
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
int commodity_compareTech(const void *commodity1, const void *commodity2)
Function meant for use with C89, C99 algorithm qsort().
Definition commodity.c:245
Commodity * commodity_getW(const char *name)
Gets a commodity by name without warning.
Definition commodity.c:166
int ndata_matchExt(const char *path, const char *ext)
Sees if a file matches an extension.
Definition ndata.c:420
char ** ndata_listRecursive(const char *path)
Lists all the visible files in a directory, at any depth.
Definition ndata.c:286
xmlDocPtr xml_parsePhysFS(const char *filename)
Analogous to xmlParseMemory/xmlParseFile.
Definition nxml.c:70
int outfit_compareTech(const void *outfit1, const void *outfit2)
Function meant for use with C89, C99 algorithm qsort().
Definition outfit.c:302
const Outfit * outfit_getW(const char *name)
Gets an outfit by name without warning on no-find.
Definition outfit.c:237
static const double c[]
Definition rng.c:256
const Ship * ship_getW(const char *name)
Gets a ship based on its name without warning.
Definition ship.c:113
int ship_compareTech(const void *arg1, const void *arg2)
Comparison function for qsort().
Definition ship.c:142
Represents a commodity.
Definition commodity.h:57
char * name
Definition commodity.h:58
A ship outfit, depends radically on the type.
Definition outfit.h:372
char * name
Definition outfit.h:373
Represents a space ship.
Definition ship.h:97
char * name
Definition ship.h:100
Group of tech items, basic unit of the tech trees.
Definition tech.c:59
char * name
Definition tech.c:60
char * filename
Definition tech.c:61
tech_item_t * items
Definition tech.c:62
Item contained in a tech group.
Definition tech.c:43
const Outfit * outfit
Definition tech.c:48
double chance
Definition tech.c:45
const Commodity * comm
Definition tech.c:50
union tech_item_t::@174006102143025056261247062217121166136264067037 u
tech_item_type_t type
Definition tech.c:44
const tech_group_t * grpptr
Definition tech.c:52
void * ptr
Definition tech.c:47
int grp
Definition tech.c:51
const Ship * ship
Definition tech.c:49
static char * tech_getItemName(tech_item_t *item)
Gets an item's name.
Definition tech.c:217
static tech_item_t * tech_addItemCommodity(tech_group_t *grp, const char *name)
Loads a group item pertaining to a outfit.
Definition tech.c:423
void tech_free(void)
Cleans up after the tech stuff.
Definition tech.c:161
Ship ** tech_getShipArray(tech_group_t **tech, int num)
Gets the ships from an array of techs.
Definition tech.c:913
int tech_load(void)
Loads the tech information.
Definition tech.c:106
Commodity ** tech_getCommodity(const tech_group_t *tech)
Gets all of the ships associated to a tech group.
Definition tech.c:960
int tech_checkOutfit(const tech_group_t *tech, const Outfit *o)
Checks to see if there is an outfit in the tech group.
Definition tech.c:980
int tech_groupWrite(xmlTextWriterPtr writer, tech_group_t *grp)
Writes a group in an xml node.
Definition tech.c:239
static int tech_parseFile(tech_group_t *tech, const char *file)
Parses an XML tech node.
Definition tech.c:263
static void tech_createMetaGroup(tech_group_t *grp, tech_group_t **tech, int num)
Creates a meta-tech group pointing only to other groups.
Definition tech.c:608
int tech_hasShip(const tech_group_t *tech, const Ship *ship)
Checks to see whether a tech group contains a ship.
Definition tech.c:739
int tech_rmItemTech(tech_group_t *tech, const char *value)
Removes an item from a tech.
Definition tech.c:506
int tech_hasCommodity(const tech_group_t *tech, const Commodity *comm)
Checks to see whether a tech group contains a commodity.
Definition tech.c:771
tech_group_t * tech_groupCreate(void)
Creates a tech group.
Definition tech.c:196
static int tech_addItemGroupPointer(tech_group_t *grp, const tech_group_t *ptr)
Adds a group pointer to a group.
Definition tech.c:571
int tech_getItemCount(const tech_group_t *tech)
Gets the number of techs within a given group.
Definition tech.c:785
int tech_rmItem(const char *name, const char *value)
Removes a tech item.
Definition tech.c:525
tech_item_type_t
Different tech types.
Definition tech.c:32
@ TECH_TYPE_COMMODITY
Definition tech.c:35
@ TECH_TYPE_OUTFIT
Definition tech.c:33
@ TECH_TYPE_GROUP
Definition tech.c:36
@ TECH_TYPE_GROUP_POINTER
Definition tech.c:37
@ TECH_TYPE_SHIP
Definition tech.c:34
static void tech_freeGroup(tech_group_t *grp)
Cleans up a tech group.
Definition tech.c:175
static int tech_parseXMLData(tech_group_t *tech, xmlNodePtr parent)
Parses an XML tech node.
Definition tech.c:294
int tech_hasItem(const tech_group_t *tech, const char *item)
Checks whether a given tech group has the specified item.
Definition tech.c:680
tech_group_t * tech_groupCreateXML(xmlNodePtr node)
Creates a tech group from an XML node.
Definition tech.c:185
static int tech_getID(const char *name)
Gets the ID of a tech.
Definition tech.c:558
void tech_groupDestroy(tech_group_t *grp)
Frees a tech group.
Definition tech.c:205
static void ** tech_addGroupItem(void **items, tech_item_type_t type, const tech_group_t *tech)
Recursive function for creating an array of commodities from a tech group.
Definition tech.c:623
static tech_item_t * tech_itemGrow(tech_group_t *grp)
Adds an item to a tech.
Definition tech.c:374
Commodity ** tech_getCommodityArray(tech_group_t **tech, int num)
Gets the ships from an array of techs.
Definition tech.c:937
Ship ** tech_getShip(const tech_group_t *tech)
Gets all of the ships associated to a tech group.
Definition tech.c:887
int tech_addItemTech(tech_group_t *tech, const char *value)
Adds an item to a tech.
Definition tech.c:480
int tech_addItem(const char *name, const char *value)
Adds an item to a tech.
Definition tech.c:443
Outfit ** tech_getOutfitArray(tech_group_t **tech, int num)
Gets the outfits from an array of techs.
Definition tech.c:864
Outfit ** tech_getOutfit(const tech_group_t *tech)
Gets all of the outfits associated to a tech group.
Definition tech.c:839
static int tech_parseFileData(tech_group_t *tech)
Parses an XML tech node.
Definition tech.c:349
char ** tech_getItemNames(const tech_group_t *tech, int *n)
Gets the names of all techs within a given group.
Definition tech.c:797
int tech_hasOutfit(const tech_group_t *tech, const Outfit *outfit)
Checks to see whether a tech group contains a outfit.
Definition tech.c:755
static tech_item_t * tech_addItemShip(tech_group_t *grp, const char *name)
Loads a group item pertaining to a outfit.
Definition tech.c:403
static tech_item_t * tech_addItemGroup(tech_group_t *grp, const char *name)
Loads a group item pertaining to a group.
Definition tech.c:584
char ** tech_getAllItemNames(int *n)
Gets the names of all techs.
Definition tech.c:817