Noble Ape
The Central Directories of the Noble Ape Simulation.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
body.c
Go to the documentation of this file.
1 /****************************************************************
2 
3  body.c
4 
5  =============================================================
6 
7  Copyright 1996-2014 Tom Barbalet. All rights reserved.
8 
9  Permission is hereby granted, free of charge, to any person
10  obtaining a copy of this software and associated documentation
11  files (the "Software"), to deal in the Software without
12  restriction, including without limitation the rights to use,
13  copy, modify, merge, publish, distribute, sublicense, and/or
14  sell copies of the Software, and to permit persons to whom the
15  Software is furnished to do so, subject to the following
16  conditions:
17 
18  The above copyright notice and this permission notice shall be
19  included in all copies or substantial portions of the Software.
20 
21  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  OTHER DEALINGS IN THE SOFTWARE.
29 
30  This software and Noble Ape are a continuing work of Tom Barbalet,
31  begun on 13 June 1996. No apes or cats were harmed in the writing
32  of this software.
33 
34  ****************************************************************/
35 
36 #include "entity.h"
37 #include "entity_internal.h"
38 
46 static void body_action_give(noble_simulation * sim, noble_being * local, noble_being * other, n_byte2 carrying)
47 {
48  n_byte hand = BODY_RIGHT_HAND;
49 
50  if (carrying == 0)
51  {
52  hand = BODY_LEFT_HAND;
53  carrying = being_carried(local,hand);
54  }
55  if ((carrying != 0) &&
56  ((being_carried(other,BODY_LEFT_HAND)==0) ||
57  (being_carried(other,BODY_RIGHT_HAND)==0)))
58  {
61 
62  episodic_interaction(sim, local, other, EVENT_GIVEN, EPISODIC_AFFECT_ZERO, carrying);
63  episodic_interaction(sim, other, local, EVENT_GIVEN_BY, AFFECT_RECEIVE, carrying);
64 
65  being_drop(local,hand);
66  if (being_carried(other,BODY_RIGHT_HAND)==0)
67  {
68  being_take(other,BODY_RIGHT_HAND,carrying);
69  }
70  else
71  {
72  being_take(other,BODY_LEFT_HAND,carrying);
73  }
74  }
75 }
76 
84 static void body_action_bash(noble_simulation * sim, noble_being * local, noble_being * other, n_byte2 carrying)
85 {
86  n_byte hand = BODY_RIGHT_HAND;
87  n_int index, hit = 0;
88  noble_social * graph;
89 
90  if (carrying == 0)
91  {
92  hand = BODY_LEFT_HAND;
93  carrying = being_carried(local,hand);
94  }
95  if (carrying!=0)
96  {
97  if ((carrying & INVENTORY_BRANCH) || (carrying & INVENTORY_ROCK))
98  {
100  GET_A(other,ATTENTION_BODY) = BODY_BACK;
101  index = get_noble_social(other,local,sim);
102  if (index>-1)
103  {
104  graph = being_social(other);
105  if (!graph) return;
106  if (graph[index].friend_foe>1) graph[index].friend_foe-=2;
107  }
108  if ((carrying & INVENTORY_ROCK) && (being_random(other)>THROW_ACCURACY))
109  {
110  hit=1;
112  }
113  if ((carrying & INVENTORY_BRANCH) && (being_random(other)>WHACK_ACCURACY))
114  {
115  hit=1;
117  }
118  }
119  if (carrying & INVENTORY_BRANCH)
120  {
121  if (hit != 0)
122  {
124  episodic_interaction(sim, other, local, EVENT_WHACKED_BY, AFFECT_WHACKED, 0);
125  }
126  }
127  if (carrying & INVENTORY_ROCK)
128  {
130  if (hit != 0)
131  {
132  episodic_interaction(sim, other, local, EVENT_HURLED_BY, AFFECT_HURL, 0);
133  }
134  }
135  }
136 
137 }
138 
148 static void body_action_interactive(noble_simulation * sim, noble_being * local, noble_being * other,
149  n_byte local_attention, n_byte other_attention, n_byte kind)
150 {
151  GET_A(local,ATTENTION_BODY) = local_attention;
152  GET_A(other,ATTENTION_BODY) = other_attention;
153  episodic_interaction(sim, local, other, kind, EPISODIC_AFFECT_ZERO, 0);
154  episodic_interaction(sim, other, local, kind+1, EPISODIC_AFFECT_ZERO, 0);
155 }
156 
157 /*** This block should also be the same function ***/
158 
159 static void body_action_interactive_change(noble_simulation * sim, noble_being * local, noble_being * other,
160  n_byte local_attention, n_byte other_attention, n_byte kind, n_byte positive, n_int affect)
161 {
162  n_int index;
163  GET_A(local,ATTENTION_BODY) = local_attention;
164  GET_A(other,ATTENTION_BODY) = other_attention;
165  index = get_noble_social(other,local,sim);
166  if (index>-1)
167  {
168  noble_social * graph = being_social(other);
169  if (!graph) return;
170  if (positive)
171  {
172  if (graph[index].friend_foe<255) graph[index].friend_foe++;
173  }
174  else
175  {
176  if (graph[index].friend_foe>0) graph[index].friend_foe--;
177  }
178  }
179 
180  episodic_interaction(sim, local, other, kind, EPISODIC_AFFECT_ZERO, 0);
181  episodic_interaction(sim, other, local, kind+1, affect, 0);
182 }
183 
192 static void body_action_hand_object(noble_simulation * sim, noble_being * local, n_byte2 carrying, n_byte hand, n_byte kind)
193 {
194  if (carrying == 0)
195  {
196  hand = BODY_LEFT_HAND;
197  carrying = being_carried(local,hand);
198  }
199  if (carrying!=0)
200  {
201  if (carrying & INVENTORY_BRANCH)
202  {
203  episodic_self(sim, local, kind, EPISODIC_AFFECT_ZERO, INVENTORY_BRANCH);
204  }
205  else
206  {
207  if (carrying & INVENTORY_TWIG)
208  {
209  episodic_self(sim, local, kind, EPISODIC_AFFECT_ZERO, INVENTORY_TWIG);
210  }
211  else
212  {
213  if (carrying & INVENTORY_SPEAR)
214  {
215  episodic_self(sim, local, kind, EPISODIC_AFFECT_ZERO, INVENTORY_SPEAR);
216  }
217  }
218  }
219  }
220 }
221 
229 static void body_action_jab(noble_simulation * sim, noble_being * local, n_byte2 carrying, n_byte hand)
230 {
231  enum inventory_type carrying2 = being_carried(local,BODY_LEFT_HAND);
232  if ((carrying & INVENTORY_SPEAR) ||
233  (carrying2 & INVENTORY_SPEAR))
234  {
235  n_int az;
236  n_vect2 location_vector,facing_vector,slope_vector;
237 
238  vect2_byte2(&location_vector, being_location(local));
239  being_facing_vector(local, &facing_vector, 4);
240  land_vect2(&slope_vector,&az, sim->land, &location_vector);
241 
242  if ((az > WATER_MAP) && (az < TIDE_MAX))
243  {
244  /* some probability of spearing a fish */
245  if (being_random(local)<FISHING_PROB)
246  {
247  /* carry fish */
248  if (carrying & INVENTORY_SPEAR)
249  {
251  }
252  else
253  {
254  being_take(local,hand, INVENTORY_FISH);
255  }
256  episodic_self(sim, local, EVENT_FISH, AFFECT_FISH, 0);
257  }
258  }
259  }
260 }
261 
269 static void body_action_bash_objects(noble_simulation * sim, noble_being * local, n_byte2 carrying, n_byte hand)
270 {
271  enum inventory_type carrying2 = being_carried(local,BODY_LEFT_HAND);
272  if ((carrying & INVENTORY_ROCK) && (carrying2 & INVENTORY_ROCK))
273  {
275  being_drop(local,hand);
276  being_take(local,hand,INVENTORY_SCRAPER);
277  }
278  if (((carrying & INVENTORY_ROCK) && (carrying2 & INVENTORY_NUT)) ||
279  ((carrying & INVENTORY_NUT) && (carrying2 & INVENTORY_ROCK)))
280  {
282  if (carrying & INVENTORY_NUT)
283  {
284  being_drop(local,hand);
285  being_take(local,hand,INVENTORY_NUT_CRACKED);
286  }
287  else
288  {
289  being_drop(local,BODY_LEFT_HAND);
291  }
292  }
293  if (((carrying & INVENTORY_BRANCH) && (carrying2 & INVENTORY_SCRAPER)) ||
294  ((carrying & INVENTORY_SCRAPER) && (carrying2 & INVENTORY_BRANCH)))
295  {
297  if (carrying & INVENTORY_BRANCH)
298  {
299  being_drop(local,hand);
300  being_take(local,hand,INVENTORY_SPEAR);
301  }
302  else
303  {
304  being_drop(local,BODY_LEFT_HAND);
305  being_take(local,BODY_LEFT_HAND,INVENTORY_SPEAR);
306  }
307  }
308  if (((carrying & INVENTORY_BRANCH) && (carrying2 & INVENTORY_NUT)) ||
309  ((carrying & INVENTORY_NUT) && (carrying2 & INVENTORY_BRANCH)))
310  {
312  if (carrying & INVENTORY_NUT)
313  {
314  being_drop(local,hand);
315  being_take(local,hand,INVENTORY_NUT_CRACKED);
316  }
317  else
318  {
319  being_drop(local,BODY_LEFT_HAND);
321  }
322  }
323 }
324 
333 static void body_action_chew(noble_simulation * sim, noble_being * local, n_byte2 carrying, n_byte hand)
334 {
335  if (!((carrying & INVENTORY_GRASS) ||
336  (carrying & INVENTORY_TWIG) ||
337  (carrying & INVENTORY_FISH) ||
338  (carrying & INVENTORY_BIRD_EGGS) ||
339  (carrying & INVENTORY_LIZARD_EGGS) ||
340  (carrying & INVENTORY_NUT_CRACKED)))
341  {
342  hand = BODY_LEFT_HAND;
343  carrying = being_carried(local,hand);
344  }
345  if ((carrying & INVENTORY_GRASS) ||
346  (carrying & INVENTORY_TWIG) ||
347  (carrying & INVENTORY_FISH) ||
348  (carrying & INVENTORY_BIRD_EGGS) ||
349  (carrying & INVENTORY_LIZARD_EGGS) ||
350  (carrying & INVENTORY_NUT_CRACKED))
351  {
352  if (hand == BODY_RIGHT_HAND)
353  {
354  carrying |= 1;
355  }
356  episodic_self(sim, local,EVENT_CHEW, EPISODIC_AFFECT_ZERO, carrying);
357  }
358  if (carrying & INVENTORY_GRASS)
359  {
362  being_drop(local,hand);
363  }
364  else
365  {
366  if (carrying & INVENTORY_FISH)
367  {
370  being_drop(local,hand);
371  }
372  else
373  {
374  if (carrying & INVENTORY_NUT_CRACKED)
375  {
378  being_drop(local,hand);
379  }
380  else
381  {
382  if (carrying & INVENTORY_BIRD_EGGS)
383  {
386  being_drop(local,hand);
387  }
388  else
389  {
390  if (carrying & INVENTORY_LIZARD_EGGS)
391  {
394  being_drop(local,hand);
395  }
396  }
397  }
398  }
399  }
400 }
408 static void body_action_swap_hands(noble_simulation * sim, noble_being * local, n_byte2 carrying, n_byte hand)
409 {
410  if ((carrying != 0) && (being_carried(local,BODY_LEFT_HAND)==0))
411  {
412  being_drop(local,hand);
413  being_take(local,BODY_LEFT_HAND,carrying);
414  }
415  else
416  {
417  if ((carrying == 0) && (being_carried(local,BODY_LEFT_HAND)!=0))
418  {
419  carrying = being_carried(local,BODY_LEFT_HAND);
420  being_drop(local,BODY_LEFT_HAND);
421  being_take(local,hand,carrying);
422  }
423  }
424 }
425 
433 static void body_action_drop(noble_simulation * sim, noble_being * local, n_byte2 carrying, n_byte hand)
434 {
435  if (carrying == 0)
436  {
437  hand = BODY_LEFT_HAND;
438  carrying = being_carried(local,hand);
439  }
440  if (carrying != 0)
441  {
442  being_drop(local,hand);
443  episodic_self(sim, local, EVENT_DROP, EPISODIC_AFFECT_ZERO, carrying);
444  }
445 }
446 
454 static void body_action_pickup(noble_simulation * sim, noble_being * local, n_byte2 carrying, n_byte hand)
455 {
456  if ((carrying != 0) && (!being_posture_under(local,POSTURE_CROUCHING)))
457  {
458  hand = BODY_LEFT_HAND;
459  carrying = being_carried(local,hand);
460  }
461  if (carrying == 0)
462  {
463  n_int az;
464  n_vect2 location_vector,facing_vector,slope_vector;
465  vect2_byte2(&location_vector, being_location(local));
466  being_facing_vector(local, &facing_vector, 4);
467  land_vect2(&slope_vector,&az,sim->land,&location_vector);
468 
469  if (az > WATER_MAP)
470  {
471  if (az > TIDE_MAX)
472  {
473  /* TODO handle this logic centrally */
474 
475  n_int grass, trees, bush;
476  food_values(sim->land, being_location_x(local), being_location_y(local), &grass, &trees, &bush);
477 
478 
479  if ((grass>bush) && (grass>trees))
480  {
481  being_take(local,hand, INVENTORY_GRASS);
482  episodic_self(sim, local, EVENT_PICKUP,EPISODIC_AFFECT_ZERO, INVENTORY_GRASS);
483  }
484  if ((trees>grass) && (trees>bush))
485  {
487  {
488  being_take(local,hand, INVENTORY_BRANCH);
489  episodic_self(sim, local, EVENT_PICKUP,EPISODIC_AFFECT_ZERO, INVENTORY_BRANCH);
490  }
491  else
492  {
493  being_take(local,hand, INVENTORY_NUT);
494  episodic_self(sim, local, EVENT_PICKUP,EPISODIC_AFFECT_ZERO, INVENTORY_NUT);
495  }
496  }
497  if ((bush>grass) && (bush>trees))
498  {
499  being_take(local,hand, INVENTORY_TWIG);
500  episodic_self(sim, local, EVENT_PICKUP,EPISODIC_AFFECT_ZERO, INVENTORY_TWIG);
501  }
502  }
503  else
504  {
505  being_take(local,hand, INVENTORY_ROCK);
506  episodic_self(sim, local, EVENT_PICKUP,EPISODIC_AFFECT_ZERO, INVENTORY_ROCK);
507  }
508  }
509  }
510 }
511 
520  noble_simulation * sim,
521  noble_being * local,
522  noble_being * other,
523  n_byte action)
524 {
525  n_byte2 carrying;
526  n_byte hand = BODY_RIGHT_HAND;
527 
528  if (being_awake(sim, local) == FULLY_ASLEEP)
529  {
530  return;
531  }
532 
533  carrying = being_carried(local,hand);
534  if (other == 0L)
535  {
537  switch(action%INDIVIDUAL_ACTIONS)
538  {
539  case ACTION_JAB:
540  body_action_jab(sim, local, carrying, hand);
541  break;
542  case ACTION_BASH_OBJECTS:
543  body_action_bash_objects(sim, local, carrying, hand);
544  break;
545  case ACTION_CHEW:
546  body_action_chew(sim, local, carrying, hand);
547  break;
548  case ACTION_BRANDISH:
549  body_action_hand_object(sim, local, carrying, hand, EVENT_BRANDISH);
550  break;
551  case ACTION_DRAG:
552  body_action_hand_object(sim, local, carrying, hand, EVENT_DRAG);
553  break;
554  case ACTION_SWAP_HANDS:
555  body_action_swap_hands(sim, local, carrying, hand);
556  break;
557  case ACTION_DROP:
558  body_action_drop(sim, local, carrying, hand);
559  break;
560  case ACTION_PICKUP:
561  body_action_pickup(sim, local, carrying, hand);
562  break;
563  }
564  }
565  else
566  {
568  switch(action%SOCIAL_ACTIONS)
569  {
570  case ACTION_PROD:
571  body_action_interactive_change(sim, local, other, BODY_RIGHT_HAND, BODY_FRONT,
573  break;
574  case ACTION_HUG:
575  body_action_interactive_change(sim, local, other, BODY_FRONT, BODY_FRONT,
577  break;
578  case ACTION_SMILE:
579  body_action_interactive_change(sim, local, other, BODY_TEETH, BODY_TEETH,
581  break;
582  case ACTION_GLOWER:
583  body_action_interactive_change(sim, local, other, BODY_HEAD, BODY_HEAD,
585  break;
586  case ACTION_TICKLE:
587  body_action_interactive(sim, local, other, BODY_RIGHT_HAND, BODY_FRONT, EVENT_TICKLED);
588  break;
589  case ACTION_POINT:
590  body_action_interactive(sim, local, other, BODY_RIGHT_HAND, BODY_RIGHT_HAND, EVENT_POINT);
591  break;
592  case ACTION_PAT:
593  body_action_interactive(sim, local, other, BODY_RIGHT_HAND, BODY_BACK, EVENT_PATTED);
594  break;
595  case ACTION_BASH:
596  body_action_bash(sim, local, other, carrying);
597  break;
598  case ACTION_GIVE:
599  body_action_give(sim, local, other, carrying);
600  break;
601  }
602  }
603 }
604 
611 n_int genetics_compare(n_genetics * genetics_a, n_genetics * genetics_b)
612 {
613  n_int loop = 0;
614 
615  while (loop < CHROMOSOMES)
616  {
617  if (genetics_a[loop] != genetics_b[loop])
618  {
619  return 0;
620  }
621  loop++;
622  }
623  return 1;
624 }
625 
631 void genetics_set(n_genetics * genetics_a, n_genetics * genetics_b)
632 {
633  n_int loop = 0;
634  while (loop < CHROMOSOMES)
635  {
636  genetics_a[loop] = genetics_b[loop];
637  loop++;
638  }
639 }
640 
645 void genetics_zero(n_genetics * genetics_a)
646 {
647  n_int loop = 0;
648  while (loop < CHROMOSOMES)
649  {
650  genetics_a[loop] = 0;
651  loop++;
652  }
653 }
654 
661 static n_int genetics_unique(noble_being * local, n_int number, n_genetics * genetics)
662 {
663  n_int loop = 0;
664  if (number == 0)
665  {
666  return 1;
667  }
668  while (loop < number)
669  {
670  noble_being * local_being = &(local[loop]);
671  if (genetics_compare(being_genetics(local_being), genetics))
672  {
673  return 0;
674  }
675  loop++;
676  }
677  return 1;
678 }
679 
689 static n_int genetics_child_gene(n_genetics chromosome, n_int point, n_byte2 mutation_prob, n_byte2 * local)
690 {
692  n_int child_gene = 0;
693 
694  math_random3(local);
695  if (math_random(local) < mutation_prob)
696  {
697  mutation_type = (math_random(local) & 7);
698  switch(mutation_type)
699  {
701  case MUTATION_MATERNAL:
702  child_gene = DIPLOID(
703  (math_random(local) & 3),
704  ((CHROMOSOME_FROM_FATHER(chromosome) >> point ) & 3));
705  break;
707  case MUTATION_PATERNAL:
708  child_gene = DIPLOID(
709  ((CHROMOSOME_FROM_MOTHER(chromosome) >> point ) & 3),
710  (math_random(local) & 3));
711  break;
714  child_gene = DIPLOID(
715  ((CHROMOSOME_FROM_MOTHER(chromosome) >> point ) & 3),
716  ((CHROMOSOME_FROM_MOTHER(chromosome) >> point ) & 3));
717  break;
720  child_gene = DIPLOID(
721  ((CHROMOSOME_FROM_FATHER(chromosome) >> point ) & 3),
722  ((CHROMOSOME_FROM_FATHER(chromosome) >> point ) & 3));
723  break;
724  default:
725  math_random3(local);
726 
727  child_gene = DIPLOID(
728  (math_random(local) & 3), (math_random(local) & 3));
729  }
730  }
731  else
732  {
734  if ((math_random(local) & 1)!=0)
735  {
736  child_gene = DIPLOID(
737  ((CHROMOSOME_FROM_MOTHER(chromosome) >> point ) & 3),
738  ((CHROMOSOME_FROM_FATHER(chromosome) >> point ) & 3));
739  }
740  else
741  {
742  child_gene = DIPLOID(
743  ((CHROMOSOME_FROM_FATHER(chromosome) >> point ) & 3),
744  ((CHROMOSOME_FROM_MOTHER(chromosome) >> point ) & 3));
745  }
746  }
747  return child_gene;
748 }
749 
757 static n_genetics genetics_crossover(n_genetics mother, n_genetics father, n_byte2 * local)
758 {
759  n_int loop = 0;
760  n_genetics result = 0;
761  n_int point, point2;
762  n_int deletion_point = 16;
763  n_byte2 prob;
764  n_genetics parent;
765 
767  n_int crossover_point = (math_random(local) >> 13) << 1;
768 
770  if (math_random(local) < MUTATION_DELETION_PROB)
771  {
772  deletion_point = (math_random(local) >> 13) << 1;
773  }
774 
775  point = point2 = crossover_point - 8;
777  while(loop< 16)
778  {
779  if (loop == deletion_point) point2 -= 2;
780 
782  if (point2 < 0)
783  {
784  point2 += 16;
785  }
786  else
787  {
788  if (point2 > 15) point2 -= 16;
789  }
790 
791  if (loop < 8)
792  {
793  parent=father;
795  prob = MUTATION_CROSSOVER_PROB*50;
796  }
797  else
798  {
799  parent=mother;
801  }
802 
803  result |= ( genetics_child_gene(parent, point2, prob, local) << point );
804  loop += 2;
805  point += 2;
806  point2 += 2;
807  }
808  return result;
809 }
810 
817 static n_genetics genetics_mutate(n_genetics chromosome, n_byte2 * local)
818 {
819  n_genetics result = 0;
820  n_int point = 0;
821  n_int loop = 0;
822  n_int deletion_point = 16;
823 
825  if (math_random(local) < MUTATION_DELETION_PROB)
826  {
827  deletion_point = (math_random(local) >> 13) << 1;
828  }
829 
831  point = 0;
832  while(loop< 16)
833  {
834  if (loop == deletion_point)
835  {
836  point -= 2;
837  if (point < 0)
838  {
839  point += 16;
840  }
841  }
842  if (point > 15) point -= 16;
843 
844  result |= ( genetics_child_gene(chromosome, point, MUTATION_CROSSOVER_PROB, local) << point );
845  loop += 2;
846  point += 2;
847  }
848  return result;
849 }
850 
857 static void genetics_transpose(n_genetics * genetics, n_byte2 * local)
858 {
859  math_random3(local);
860 
862  {
866  n_byte2 local_random0 = math_random(local);
867  n_byte2 local_random1 = math_random(local);
868 
869  n_byte source_offset = (local_random0>>8)&31;
870  n_byte dest_offset = local_random1&31;
872  n_byte inversion = (local_random0>>13) & 1;
873  n_byte source_ch = (local_random1>>5) % CHROMOSOMES;
874  n_byte dest_ch = (local_random1>>7) % CHROMOSOMES;
875  n_int ctr1 = source_offset;
876  n_byte p = 0;
877  math_random3(local);
878 
879  while (p < (math_random(local)&15))
880  {
881  n_int ctr2;
882  ctr1 = (ctr1 & 31);
883 
884  if (inversion==0)
885  {
886  ctr2=(n_int)(dest_offset+p);
887  }
888  else
889  {
891  ctr2=(n_int)dest_offset-p+32;
892  }
893  ctr2 = (ctr2 & 31);
895  if ((genetics[dest_ch] & (1<<ctr2)) != 0)
896  {
897  genetics[dest_ch] ^= (1 << ctr2);
898  }
900  if ((genetics[source_ch] & (1<<ctr1)) != 0)
901  {
902  genetics[dest_ch] |= (1 << ctr2);
903  }
904  p++;
905  ctr1++;
906  }
907  }
908 }
909 
910 
911 void body_genetics(noble_being * beings, n_int number, n_genetics * genetics, n_genetics * mother_genetics, n_genetics * father_genetics, n_byte2 * local)
912 {
913  n_int ch;
914  n_byte sex = 2;
915  math_random3(local);
916  sex |= (math_random(local)&1);
917  do
918  {
919  math_random3(local);
920 
922  for (ch = 0; ch < CHROMOSOMES; ch++)
923  {
924  if (ch != CHROMOSOME_Y)
925  {
926  genetics[ch] = genetics_crossover(mother_genetics[ch], father_genetics[ch], local);
927  }
928  }
929 
931  if (sex != SEX_FEMALE)
932  {
933  genetics[CHROMOSOME_Y] = genetics_mutate(father_genetics[CHROMOSOME_Y], local);
934  }
935  else
936  {
937  genetics[CHROMOSOME_Y] = genetics_mutate(mother_genetics[CHROMOSOME_Y], local);
938  }
940  genetics_transpose(genetics, local);
942  genetics[CHROMOSOME_Y] &= ~1;
943  genetics[CHROMOSOME_Y] |= sex;
944  }
945  while (genetics_unique(beings, number, genetics) == 0);
946 }
947 
954 void body_genome(n_byte maternal, n_genetics * genome, n_byte * genome_str)
955 {
956  n_byte string_point = 0;
957  n_int ch, value;
958 
959  n_byte nucleotide[] = { 'A', 'T', 'C', 'G' };
961  for (ch = 0; ch < CHROMOSOMES; ch++)
962  {
966  n_byte gene_point = 0;
967  while (gene_point < 16)
968  {
969  if (maternal!=0)
970  {
972  value = ( CHROMOSOME_FROM_MOTHER(genome[ch]) >> gene_point ) & 3;
973  }
974  else
975  {
977  value = ( CHROMOSOME_FROM_FATHER(genome[ch]) >> gene_point ) & 3;
978  }
979  genome_str[string_point++] = nucleotide[value];
980  gene_point += 2;
981  }
982  }
983  genome_str[string_point] = 0;
984 }
985