Noble Ape
The Central Directories of the Noble Ape Simulation.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
social.c
Go to the documentation of this file.
1 /****************************************************************
2 
3  social.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 
40 #include "entity.h"
41 #include "entity_internal.h"
42 
45 #define GENE_STATUS_PREFERENCE(gene) GENE_VAL_REG(gene, 15, 12, 10, 1)
46 
49 #define GENE_PIGMENTATION_PREFERENCE(gene) GENE_VAL_REG(gene, 5, 3, 11, 4)
50 
53 #define GENE_HEIGHT_PREFERENCE(gene) GENE_VAL_REG(gene, 9, 8, 14, 10)
54 
57 #define GENE_FRAME_PREFERENCE(gene) GENE_VAL_REG(gene, 9, 0, 8, 2)
58 
61 #define GENE_HAIR_PREFERENCE(gene) GENE_VAL_REG(gene, 10, 7, 14, 15)
62 
65 #define GENE_GROOM(gene) GENE_VAL_REG(gene, 14, 2, 5, 10)
66 
69 #define GENE_AGGRESSION(gene) GENE_VAL_REG(gene, 11, 3, 5, 0)
70 
73 #define GENE_MATE_BOND(gene) GENE_VAL_REG(gene, 10, 2, 4, 0)
74 
77 #define GENE_INCEST_AVERSION(gene) GENE_VAL_REG(gene, 10, 8, 4, 9)
78 
81 #define GENE_LATENT_ENERGY_USE(gene) GENE_VAL_REG(gene, 14, 3, 6, 10)
82 
83 #ifdef FEATURE_SET
84 
85 static void noble_feature_copy(noble_feature * to, noble_feature * from)
86 {
87  to->type = from->type;
88  to->value = from->value;
89  to->frequency = from->frequency;
90 }
91 
92 static void noble_feature_set(noble_feature * to, n_byte feature_type, n_byte2 feature_value)
93 {
94  to->type = (n_byte)feature_type;
95  to->value = (n_byte2)feature_value;
96  to->frequency = (n_byte2)1;
97 }
98 
105 static n_int noble_featureset_feature_index(noble_featureset * s,
106  n_byte feature_type)
107 {
108  n_int i=0;
109 
110  while (i < s->feature_number)
111  {
112  if (s->features[i].type >= feature_type)
113  {
114  break;
115  }
116  i++;
117  }
118  if (i == s->feature_number)
119  {
120  return -1;
121  }
122  return i;
123 }
124 
129 static void noble_featureset_normalise_feature_frequencies(noble_featureset *s)
130 {
131  n_uint i, tot=0;
132  n_uint max = MAX_FEATURE_FREQUENCY>>1;
133 
135  for (i = 0; i < s->feature_number; i++)
136  {
137  tot += (n_uint)s->features[i].frequency;
138  }
139 
140  if (tot == 0) tot = 1;
141 
142  for (i = 0; i < s->feature_number; i++)
143  {
144  s->features[i].frequency = (n_byte2)((n_uint)s->features[i].frequency * max / tot);
145  }
146 }
147 
155 static n_int noble_featureset_update(noble_featureset * s,
156  n_byte feature_type,
157  n_int feature_value)
158 {
160  n_int feature_index = noble_featureset_feature_index(s, feature_type);
161  n_byte2 min;
162  n_int i,j;
163 
164  if (s->features[feature_index].type == (n_byte)feature_type)
165  {
167  s->features[feature_index].value = (n_byte2)feature_value;
168  s->features[feature_index].frequency++;
171  if (s->features[feature_index].frequency > MAX_FEATURE_FREQUENCY)
172  {
173  noble_featureset_normalise_feature_frequencies(s);
174  }
175  return 0;
176  }
177  else
178  {
179  if (s->feature_number < MAX_FEATURESET_SIZE)
180  {
182  if (s->feature_number > 1)
183  {
184  for (i = (n_int)s->feature_number-1; i >= (n_int)feature_index; i--)
185  {
186  noble_feature_copy(&(s->features[i+1]), &(s->features[i]));
187  }
188  }
189 
190  i = feature_index;
191  s->feature_number++;
192  noble_feature_set(&(s->features[i]), (n_byte)feature_type, (n_byte2)feature_value);
193  return 0;
194  }
195  else
196  {
198  min = s->features[0].frequency;
199  feature_index = 0;
200  for (i = 1; i < (n_int)s->feature_number; i++)
201  {
202  if (s->features[i].frequency < min)
203  {
204  min = s->features[i].frequency;
205  feature_index = i;
206  }
207  }
209  j = 0;
210  for (i = 0; i < (n_int)s->feature_number; i++)
211  {
212  if (s->features[i].type >= (n_byte)feature_type)
213  {
214  j = i;
215  break;
216  }
217  }
218  for (i = (n_int)feature_index; i > j; i--)
219  {
220  noble_feature_copy(&(s->features[i]), &(s->features[i-1]));
221  }
222 
223 
224  noble_feature_set(&(s->features[j]), (n_byte)feature_type, (n_byte2)feature_value);
225 
226  for (i = 0; i < (n_int)s->feature_number; i++)
227  {
228  for (j = i+1; j < (n_int)s->feature_number; j++)
229  {
230  if (s->features[j].type < s->features[i].type)
231  {
232  feature_type = s->features[i].type;
233  s->features[i].type = s->features[j].type;
234  s->features[j].type = (n_byte)feature_type;
235  }
236  }
237  }
238  }
239  }
240  return -1;
241 }
242 
249 static n_int featureset_match_threshold(n_byte feature_type)
250 {
251  if (feature_type == FEATURESET_TERRITORY) return 1;
252  return 2;
253 }
254 
259 static void social_normalise_stereotype_observations(
260  noble_being * local_being)
261 {
262  noble_social * graph;
263  n_uint i, tot=0;
264  noble_featureset * s;
265  n_uint max = MAX_FEATURESET_OBSERVATIONS>>1;
266 
268  graph = being_social(local_being);
269 
270  if (graph==0) return;
271 
272  for (i = SOCIAL_SIZE_BEINGS; i < SOCIAL_SIZE; i++)
273  {
274  if (!SOCIAL_GRAPH_ENTRY_EMPTY(graph,i))
275  {
276  s = &graph[i].classification;
277  tot += (n_uint)s->observations;
278  }
279  }
280 
281  if (tot == 0) return;
282 
283  for (i = SOCIAL_SIZE_BEINGS; i < SOCIAL_SIZE; i++)
284  {
285  if (!SOCIAL_GRAPH_ENTRY_EMPTY(graph,i))
286  {
287  s = &graph[i].classification;
288  s->observations =
289  (n_byte2)((n_uint)s->observations * max / tot);
290  }
291  }
292 }
293 
302 static n_int social_get_stereotype(
303  noble_being * meeter_being,
304  n_int social_graph_index)
305 {
306  n_int i,j,diff,dv,index,hits,min=0,result=-1;
307  n_byte normalise_features;
308  noble_social * meeter_social_graph;
309  noble_featureset * s1, * s2;
310 
312  meeter_social_graph = being_social(meeter_being);
313 
314  if (meeter_social_graph==0) return -1;
315 
317  s2 = &meeter_social_graph[social_graph_index].classification;
318 
322  for (i = SOCIAL_SIZE_BEINGS; i < SOCIAL_SIZE; i++)
323  {
324  if (!SOCIAL_GRAPH_ENTRY_EMPTY(meeter_social_graph,i))
325  {
327  s1 = &meeter_social_graph[i].classification;
328  normalise_features = 0;
329  diff = 0;
330  hits = 0;
332  for (j = 0; j < s1->feature_number; j++)
333  {
335  index = noble_featureset_feature_index(s2, s1->features[j].type);
336  if (index > -1)
337  {
338  hits++;
340  dv = (n_int)s1->features[j].value -
341  (n_int)s2->features[index].value;
342  if (dv < 0) dv = -dv;
343 
346  diff += dv;
347 
350  if (dv < featureset_match_threshold(s1->features[j].type))
351  {
353  s1->features[j].frequency++;
354  if (s1->features[j].frequency > MAX_FEATURE_FREQUENCY)
355  {
356  normalise_features = 1;
357  }
358  }
359  }
360  }
363  if (hits == s1->feature_number)
364  {
365  if ((result == -1) || (diff < min))
366  {
367  min = diff;
368  result = i;
369  }
372  s1->observations++;
373  if (s1->observations > MAX_FEATURESET_OBSERVATIONS)
374  {
375  social_normalise_stereotype_observations(meeter_being);
376  }
377  }
378 
380  if (normalise_features == 1)
381  {
382  noble_featureset_normalise_feature_frequencies(s1);
383  }
384  }
385  }
386  return result;
387 }
388 
395 static void social_meet_update_features(
396  noble_being * meeter_being,
397  noble_being * met_being,
398  n_int social_graph_index)
399 {
400  noble_social * meeter_social_graph;
401 #ifdef TERRITORY_ON
402  n_uint idx;
403 #endif
404 
406  meeter_social_graph = being_social(meeter_being);
407 
408  if (meeter_social_graph==0) return;
409 
415  noble_featureset_update(&meeter_social_graph[social_graph_index].classification,
417  GENE_PIGMENTATION(being_genetics(met_being)));
418 
419  noble_featureset_update(&meeter_social_graph[social_graph_index].classification,
421  GENE_HAIR(being_genetics(met_being)));
422 
423  noble_featureset_update(&meeter_social_graph[social_graph_index].classification,
425  GET_H(met_being));
426 
427  noble_featureset_update(&meeter_social_graph[social_graph_index].classification,
429  GET_BODY_FAT(met_being));
430 
431  noble_featureset_update(&meeter_social_graph[social_graph_index].classification,
433  GENE_EYE_SHAPE(being_genetics(met_being)));
434 
435  noble_featureset_update(&meeter_social_graph[social_graph_index].classification,
437  GENE_EYE_COLOR(being_genetics(met_being)));
438 
439  noble_featureset_update(&meeter_social_graph[social_graph_index].classification,
441  GENE_EYE_SEPARATION(being_genetics(met_being)));
442 
443  noble_featureset_update(&meeter_social_graph[social_graph_index].classification,
445  GENE_NOSE_SHAPE(being_genetics(met_being)));
446 
447  noble_featureset_update(&meeter_social_graph[social_graph_index].classification,
449  GENE_EAR_SHAPE(being_genetics(met_being)));
450 
451  noble_featureset_update(&meeter_social_graph[social_graph_index].classification,
453  GENE_EYEBROW_SHAPE(being_genetics(met_being)));
454 
455  noble_featureset_update(&meeter_social_graph[social_graph_index].classification,
457  GENE_MOUTH_SHAPE(being_genetics(met_being)));
458 
459 #ifdef TERRITORY_ON
462 
463  noble_featureset_update(&meeter_social_graph[social_graph_index].classification,
465  meeter_being->territory[idx].name);
466 #endif
467 }
468 
469 #endif
470 
480  noble_simulation * local_sim,
481  noble_being * local_being,
482  n_int social_graph_index,
483  n_byte met,
484  n_string name)
485 {
486  noble_social * local_social_graph;
487 
489  local_social_graph = being_social(local_being);
490 
491  if (local_social_graph==0) return;
492 
493  switch(local_social_graph[social_graph_index].entity_type)
494  {
495  case ENTITY_BEING:
496  {
497  being_name_byte2(local_social_graph[social_graph_index].first_name[met], local_social_graph[social_graph_index].family_name[met], name);
498  break;
499  }
500  case ENTITY_BEING_GROUP:
501  (void)SHOW_ERROR("Unimplemented being group entity type");
502  break;
503  case ENTITY_OBJECT:
504  (void)SHOW_ERROR("Unimplemented object entity type");
505  break;
506  case ENTITY_TERRITORY:
507  (void)SHOW_ERROR("Unimplemented territory entity type");
508  break;
509  default:
510  (void)SHOW_ERROR("Unimplemented entity type");
511  break;
512  }
513 }
514 
523 static void social_group_align_preferences(
524  noble_simulation * local_sim,
525  noble_being * meeter_being,
526  noble_being * met_being,
527  n_int social_graph_index)
528 {
529  n_int i, incr = -1;
530  noble_social * social_graph;
531 
533  if ((meeter_being==met_being) || (social_graph_index < 1)) return;
534 
536  social_graph = being_social(meeter_being);
537 
538  if (social_graph == 0L) return;
539 
541  if (SOCIAL_GRAPH_ENTRY_EMPTY(social_graph,social_graph_index)) return;
542 
545  if (social_graph[social_graph_index].friend_foe >=
546  (n_byte)social_respect_mean(local_sim,meeter_being))
547  {
548  incr = 1;
549  }
550 
552  for (i = 0; i < PREFERENCES; i++)
553  {
554  n_int resultant = meeter_being->learned_preference[i];
555  if (resultant < met_being->learned_preference[i])
556  {
557  if ((incr > 0) || ((incr < 0) && (resultant > 0)))
558  {
559  resultant += incr;
560  }
561  }
562  else if (resultant > met_being->learned_preference[i])
563  {
564  if ((incr > 0) || ((incr < 0) && (meeter_being->learned_preference[i]<255)))
565  {
566  resultant -= incr;
567  }
568  }
569  meeter_being->learned_preference[i] = (n_byte)resultant;
570  }
571 }
572 
579 static n_int social_attraction_pigmentation(
580  noble_being * being_meeter,
581  noble_being * being_met)
582 {
583  n_int ppref, pdiff;
584  n_byte fem = (FIND_SEX(GET_I(being_meeter)) == SEX_FEMALE);
585 
588  ppref = NATURE_NURTURE(
591 
592  pdiff = GENE_PIGMENTATION(being_genetics(being_met)) - ppref;
593 
594  if ((pdiff >= -2) && (pdiff <= 2))
595  {
596  pdiff = ABS(pdiff);
597  return (3 - pdiff);
598  }
599  return 0;
600 }
601 
608 static n_int social_attraction_hair(
609  noble_being * meeter_being,
610  noble_being * met_being)
611 {
612  n_int ppref, pdiff;
613  n_byte fem = (FIND_SEX(GET_I(meeter_being)) == SEX_FEMALE);
614 
618  ppref = NATURE_NURTURE(
619  GENE_HAIR_PREFERENCE(being_genetics(meeter_being)),
620  meeter_being->learned_preference[PREFERENCE_MATE_HAIR_MALE+fem]);
621  pdiff = GENE_HAIR(being_genetics(met_being)) - ppref;
622 
623  if ((pdiff >= -2) && (pdiff <= 2))
624  {
625  pdiff = ABS(pdiff);
626  return (3 - pdiff);
627  }
628  return 0;
629 }
630 
637 static n_int social_attraction_height(
638  noble_being * meeter_being,
639  noble_being * met_being)
640 {
641  n_int ppref;
642  n_byte fem = (FIND_SEX(GET_I(meeter_being)) == SEX_FEMALE);
643 
647  ppref = NATURE_NURTURE(
648  GENE_HEIGHT_PREFERENCE(being_genetics(meeter_being)),
650 
655  if (ppref >= 8)
656  {
657  if ((ppref>=12) && (GET_H(met_being) > GET_H(meeter_being)))
658  {
660  return 1;
661  }
662  else
663  {
664  if ((ppref<12) && (GET_H(met_being) < GET_H(meeter_being)))
665  {
667  return 1;
668  }
669  }
670  }
671  return 0;
672 }
673 
680 static n_int social_attraction_frame(
681  noble_being * meeter_being,
682  noble_being * met_being)
683 {
684  n_int ppref;
685  n_byte fem = (FIND_SEX(GET_I(meeter_being)) == SEX_FEMALE);
686 
690  ppref = NATURE_NURTURE(
691  GENE_FRAME_PREFERENCE(being_genetics(meeter_being)),
693 
694  if ((ppref>6) && (ppref<=11) && (GET_BODY_FAT(met_being) > GET_BODY_FAT(meeter_being)))
695  {
697  return 1;
698  }
699  else
700  {
701  if ((ppref>11) && (GET_BODY_FAT(met_being) < GET_BODY_FAT(meeter_being)))
702  {
704  return 1;
705  }
706  }
707  return 0;
708 }
709 
717 static n_int social_attraction_pheromone(
718  noble_being * meeter_being,
719  noble_being * met_being)
720 {
721  n_int ch, i, different = 0;
722  n_genetics * meeter_genetics = being_genetics(meeter_being);
723  n_genetics * met_genetics = being_genetics(met_being);
724 
725  for (ch = 0; ch < CHROMOSOMES; ch++)
726  {
727  for (i = 0; i < 32; i++)
728  {
729  if (((meeter_genetics[ch] >> i) & 1) != ((met_genetics[ch] >> i) & 1))
730  {
731  different++;
732  }
733  }
734  }
735  if (different < MINIMUM_GENETIC_VARIATION)
736  {
737  return 0-GENE_INCEST_AVERSION(meeter_genetics);
738  }
739  else
740  {
741  return 1;
742  }
743 }
744 
753  noble_being * meeter_being,
754  noble_being * met_being,
755  noble_simulation * sim)
756 {
757  n_byte2 i;
758  noble_social * graph = being_social(meeter_being);
759 
760  if (!graph) return -1;
761 
762  for (i=1; i<SOCIAL_SIZE_BEINGS; i++)
763  {
764  if (!SOCIAL_GRAPH_ENTRY_EMPTY(graph,i))
765  {
766  if (graph[i].entity_type==ENTITY_BEING)
767  {
768  if (being_name_comparison(met_being, graph[i].first_name[BEING_MET], graph[i].family_name[BEING_MET]))
769  {
770  return i;
771  }
772  }
773  }
774  }
775  return -1;
776 }
777 
785 static n_int get_stranger_link(
786  noble_being * meeter_being,
787  noble_being * met_being,
788  noble_simulation * sim)
789 {
790  n_byte2 i=1;
791  n_int stranger_index=-1;
792  n_byte2 stranger=65535, familiarity=0;
793  n_int time_since_met;
794  noble_social * graph = being_social(meeter_being);
795  if (!graph) return 0;
796 
797  for (i=1; i<SOCIAL_SIZE_BEINGS; i++)
798  {
799  if (!SOCIAL_GRAPH_ENTRY_EMPTY(graph,i))
800  {
802  if (!IS_FAMILY_MEMBER(graph,i))
803  {
805  familiarity = graph[i].familiarity;
806  if (familiarity < stranger)
807  {
810  time_since_met = sim->land->date - graph[i].space_time.date;
811 
812  if ((time_since_met >= SOCIAL_FORGET_DAYS) ||
813  (graph[i].space_time.date==0))
814  {
815  stranger = familiarity;
816  stranger_index = i;
817  }
818  }
819  }
820  }
821  else
822  {
824  stranger_index = i;
825  break;
826  }
827  }
828  return stranger_index;
829 }
830 
838 static n_int social_meet(
839  noble_being * meeter_being,
840  noble_being * met_being,
841  noble_simulation * sim,
842  n_byte location_type)
843 {
844  n_int friend_or_foe, index = -1, stereotype_index = -1;
845 
846  n_byte2 familiarity = 0;
847  noble_social * graph = being_social(meeter_being);
848  n_byte2 met = 0;
849 
850  if (!graph) return -1;
851 
853  being_immune_transmit(meeter_being, met_being, PATHOGEN_TRANSMISSION_AIR);
854 
856  index = get_noble_social(meeter_being,met_being,sim);
857  if (index > 0)
858  {
859  familiarity = graph[index].familiarity;
860  met=1;
861  }
862  else
863  {
866  index = get_stranger_link(meeter_being,met_being,sim);
867  }
868 
869  if ((met == 1) || ((met == 0) && (index > 0)))
870  {
871 #ifdef FEATURE_SET
872 
873  social_meet_update_features(
874  meeter_being, met_being, index);
875 
877  stereotype_index = social_get_stereotype(
878  meeter_being, index);
879 #endif
880 
881  GET_A(meeter_being,ATTENTION_ACTOR) = (n_byte)index;
882 
884  if (met == 0)
885  {
886  if (stereotype_index > -1)
887  {
889  friend_or_foe =
890  graph[stereotype_index].friend_foe;
891  }
892  else
893  {
895  friend_or_foe =
897  social_attraction_pheromone(meeter_being,met_being) +
898  social_attraction_pigmentation(meeter_being,met_being) +
899  social_attraction_height(meeter_being,met_being) +
900  social_attraction_frame(meeter_being,met_being) +
901  social_attraction_hair(meeter_being,met_being)
902 #ifdef EPISODIC_ON
903  + episodic_met_being_celebrity(sim,meeter_being,met_being)
904 #endif
905  ;
906 
909  }
911  graph[index].entity_type = ENTITY_BEING;
912 
914  graph[index].first_name[BEING_MEETER] = being_gender_name(meeter_being);
915  graph[index].family_name[BEING_MEETER] = being_family_name(meeter_being);
917  graph[index].first_name[BEING_MET] = being_gender_name(met_being);
918  graph[index].family_name[BEING_MET] = being_family_name(met_being);
919 
921  graph[index].attraction = 0;
922 
924  if (friend_or_foe < 0) friend_or_foe = 0;
925  if (friend_or_foe > 255) friend_or_foe = 255;
926  graph[index].friend_foe = (n_byte)friend_or_foe;
927 #ifdef BRAINCODE_ON
928 
929  being_init_braincode(meeter_being,met_being,
930  graph[index].friend_foe,BRAINCODE_EXTERNAL);
931 #endif
932  }
933 
934  if (location_type == LOCATION_KNOWN)
935  {
937  graph[index].space_time.location[0] = (n_byte2)being_location_x(meeter_being);
938  graph[index].space_time.location[1] = (n_byte2)being_location_y(meeter_being);
939  }
940  else {
942  graph[index].space_time.location[0] = 0;
943  graph[index].space_time.location[1] = 0;
944  }
945 
947  graph[index].belief = being_state(met_being);
948 
950  graph[index].space_time.date = sim->land->date;
951  graph[index].space_time.time = sim->land->time;
952 
954  if (familiarity < 65535)
955  {
956  graph[index].familiarity = familiarity + 1;
957  }
958 
960  if (graph[index].friend_foe < 255)
961  {
962  graph[index].friend_foe++;
963  }
964  }
965  return index;
966 }
967 
978  noble_being * meeter_being,
979  n_byte relationship,
980  noble_simulation * sim)
981 {
982  n_int index;
983  noble_social * meeter_social_graph;
984 
986  meeter_social_graph = being_social(meeter_being);
987 
988  if (meeter_social_graph == 0L)
989  {
990  return -1;
991  }
992 
994  for (index = 1; index < SOCIAL_SIZE_BEINGS; index++)
995  {
997  if (meeter_social_graph[index].relationship == relationship)
998  {
999  return index;
1000  }
1001  }
1002  return -1;
1003 }
1004 
1014  n_byte relationship,
1015  noble_being * met_being,
1016  noble_simulation * sim)
1017 {
1018  n_int index;
1019  noble_social * meeter_social_graph;
1020 
1022  if (relationship == 0) return -1;
1023 
1025  index = social_meet(meeter_being,met_being,sim, LOCATION_UNKNOWN);
1026  if (index > -1)
1027  {
1029  meeter_social_graph = being_social(meeter_being);
1030 
1031  if (meeter_social_graph == 0L)
1032  {
1033  return -1;
1034  }
1035 
1037  meeter_social_graph[index].relationship = relationship;
1038  }
1039  return index;
1040 }
1041 
1052  noble_being * meeter_being,
1053  noble_being * met_being,
1054  n_int distance,
1055  noble_simulation *sim)
1056 {
1057  n_int being_index = -1;
1058  if (distance < SOCIAL_RANGE)
1059  {
1060  being_index = social_meet(meeter_being, met_being, sim, LOCATION_KNOWN);
1061  }
1062  return being_index;
1063 }
1064 
1076  noble_being * meeter_being,
1077  noble_being * met_being,
1078  n_int distance,
1079  n_int awake,
1080  n_byte2 familiarity,
1081  noble_simulation * sim)
1082 {
1083  n_int meeter_index, met_index;
1084  n_byte max = 0, grooming = 0, groom_decisions, groomloc, fem;
1085  n_int gpref;
1086  n_int paraprob;
1087 
1089  max = (n_byte)MAX_PARASITES(meeter_being);
1092  if (meeter_being->parasites < max)
1093  {
1094  paraprob = being_random(meeter_being);
1095  if (paraprob < PARASITE_ENVIRONMENT +
1096  (PARASITE_BREED*meeter_being->parasites))
1097  {
1098  meeter_being->parasites++;
1099  }
1100  }
1101 
1103  being_energy_delta(meeter_being, 0 - (PARASITE_ENERGY_COST*meeter_being->parasites));
1104 
1105  if (distance < PARASITE_HOP_MAX_DISTANCE)
1106  {
1108  max = (n_byte)MAX_PARASITES(met_being);
1110  if ((met_being->parasites < max) &&
1111  (met_being->parasites < meeter_being->parasites))
1112  {
1113  met_being->parasites++;
1114  meeter_being->parasites--;
1115  }
1116  }
1117 
1120  if ((awake != FULLY_ASLEEP) &&
1121  (distance < GROOMING_MAX_SEPARATION) &&
1122  (being_speed(meeter_being) < MAX_SPEED_WHILST_GROOMING))
1123  {
1124  n_int groomprob = being_random(meeter_being) & 16383;
1125  if (familiarity > 16) familiarity=16;
1126 
1128  fem = (FIND_SEX(GET_I(met_being)) == SEX_FEMALE);
1129 
1131  gpref = NATURE_NURTURE(
1132  GENE_GROOM(being_genetics(meeter_being)),
1133  meeter_being->learned_preference[PREFERENCE_GROOM_MALE+fem]);
1134 
1136  if (groomprob <
1137  GROOMING_PROB + (gpref*(1+familiarity)*GROOMING_PROB_HONOR*(1+met_being->honor)))
1138  {
1140  being_immune_transmit(meeter_being, met_being, PATHOGEN_TRANSMISSION_TOUCH);
1141  being_immune_transmit(met_being, meeter_being, PATHOGEN_TRANSMISSION_TOUCH);
1142 
1144  groomloc = GET_A(meeter_being,ATTENTION_BODY);
1145  groom_decisions = 0;
1146  while ((met_being->inventory[groomloc] & INVENTORY_GROOMED) && (groom_decisions<4))
1147  {
1148  met_being->inventory[groomloc] |= INVENTORY_GROOMED;
1149  groomloc = (n_byte)(being_random(meeter_being) % INVENTORY_SIZE);
1150  groom_decisions++;
1151  }
1153  if (met_being->inventory[groomloc] & INVENTORY_WOUND)
1154  {
1155  met_being->inventory[groomloc] = INVENTORY_GROOMED;
1156  }
1158  GET_A(meeter_being, ATTENTION_BODY) = groomloc;
1159 
1160  episodic_interaction(sim, meeter_being, met_being, EVENT_GROOM, AFFECT_GROOM, groomloc);
1161  episodic_interaction(sim, met_being, meeter_being, EVENT_GROOMED, AFFECT_GROOM, groomloc);
1162 
1164  meeter_index = social_meet(meeter_being, met_being, sim, LOCATION_KNOWN);
1165  if (meeter_index > -1)
1166  {
1167  met_index = social_meet(met_being, meeter_being, sim, LOCATION_KNOWN);
1168  if (met_index > -1)
1169  {
1170  noble_social * graph = being_social(meeter_being);
1171  if (!graph) return 0;
1172 
1173  if ((graph[meeter_index].friend_foe)<255)
1174  {
1175  graph[meeter_index].friend_foe++;
1176  }
1177  if ((graph[met_index].friend_foe)<255)
1178  {
1179  graph[met_index].friend_foe++;
1180  }
1181  }
1182  }
1185  being_honor_inc_dec(meeter_being, met_being);
1186 
1188  if (met_being->parasites >= PARASITES_REMOVED)
1189  {
1190  met_being->parasites-=PARASITES_REMOVED;
1191  }
1192  else
1193  {
1194  met_being->parasites = 0;
1195  }
1196  grooming = 1;
1197  }
1198  }
1199 
1200  return grooming;
1201 }
1202 
1213  noble_being * meeter_being,
1214  noble_being * met_being,
1215  n_uint distance,
1216  n_int is_female,
1217  noble_simulation * sim)
1218 {
1219  n_uint agro;
1220  n_byte2 ret_val = 0;
1221  noble_being * victor, * vanquished;
1222  n_int victor_index, vanquished_index;
1223  n_byte2 punchloc;
1224  n_vect2 delta;
1225 
1227  being_delta(met_being, meeter_being, &delta);
1228 
1230  if ((being_family_first_name(meeter_being) != being_family_first_name(met_being)) &&
1231  (being_family_second_name(meeter_being) != being_family_second_name(met_being)))
1232  {
1233  being_facing_towards(meeter_being, &delta);
1235  agro = GENE_AGGRESSION(being_genetics(meeter_being));
1237  if (is_female) agro >>= 3;
1238  if (being_random(meeter_being) < agro*4096 + agro*meeter_being->honor*10)
1239  {
1241  victor = meeter_being;
1242  vanquished = met_being;
1243 
1244  if (((being_random(meeter_being)&7)*being_energy(meeter_being)) <
1245  ((being_random(meeter_being)&7)*being_energy(met_being)))
1246  {
1247  victor = met_being;
1248  vanquished = meeter_being;
1249  }
1250 
1251  vanquished_index = social_meet(victor, vanquished, sim, LOCATION_KNOWN);
1252  if (vanquished_index > -1)
1253  {
1254  victor_index = social_meet(vanquished, victor, sim, LOCATION_KNOWN);
1255  if (victor_index > -1)
1256  {
1257  noble_social * victor_social_graph = being_social(victor);
1258  noble_social * vanquished_social_graph = being_social(vanquished);
1259 
1260  if ((!victor_social_graph) || (!vanquished_social_graph)) return 0;
1261 
1263  if (victor_social_graph[vanquished_index].friend_foe > SQUABBLE_DISRESPECT)
1264  {
1265  victor_social_graph[vanquished_index].friend_foe-=SQUABBLE_DISRESPECT;
1266  }
1268  if (vanquished_social_graph[victor_index].friend_foe > SQUABBLE_DISRESPECT)
1269  {
1270  vanquished_social_graph[victor_index].friend_foe-=SQUABBLE_DISRESPECT;
1271  }
1272  }
1273  }
1275  if (victor->honor < 255-SQUABBLE_HONOR_ADJUST) victor->honor += SQUABBLE_HONOR_ADJUST;
1277  if (vanquished->honor > SQUABBLE_HONOR_ADJUST) vanquished->honor -= SQUABBLE_HONOR_ADJUST;
1278 
1279  punchloc = being_random(victor) % INVENTORY_SIZE;
1280  if (distance > SQUABBLE_SHOW_FORCE_DISTANCE)
1281  {
1283  vanquished->inventory[punchloc] = 0;
1286 
1287  ret_val |= BEING_STATE_SHOWFORCE;
1288  }
1289  else
1290  {
1292  vanquished->inventory[punchloc] = INVENTORY_WOUND;
1295  being_honor_swap(victor, vanquished);
1296  ret_val |= BEING_STATE_ATTACK;
1297  }
1298 
1301  episodic_interaction(sim, victor, vanquished, EVENT_HIT, AFFECT_SQUABBLE_VICTOR, punchloc);
1302  episodic_interaction(sim, vanquished, victor, EVENT_HIT_BY, AFFECT_SQUABBLE_VANQUISHED, punchloc);
1303 
1305  if (meeter_being == vanquished)
1306  {
1307  n_vect2 negative_delta, zero = {0};
1308 
1309  vect2_subtract(&negative_delta, &zero, &delta);
1310 
1311  being_facing_towards(vanquished, &negative_delta);
1312  }
1313  else
1314  {
1315  being_facing_towards(vanquished, &delta);
1316  }
1317 
1319  being_set_speed(vanquished, SQUABBLE_FLEE_SPEED);
1320  }
1321  return ret_val;
1322  }
1323  return 0;
1324 }
1325 
1333  noble_simulation * sim,
1334  noble_being *local_being)
1335 {
1336  n_uint noble_socials=0,average=0;
1337  noble_social * local_social_graph;
1338  n_int i;
1339 
1340  local_social_graph = being_social(local_being);
1341  if (!local_social_graph) return 0;
1342 
1344  for (i=0; i<SOCIAL_SIZE; i++)
1345  {
1346  if (!SOCIAL_GRAPH_ENTRY_EMPTY(local_social_graph,i))
1347  {
1348  noble_socials++;
1349  average += (n_uint)(local_social_graph[i].friend_foe);
1350  }
1351  }
1352  if (noble_socials>0)
1353  {
1354  return average/noble_socials;
1355  }
1356  return SOCIAL_RESPECT_NORMAL;
1357 }
1358 
1367 /*static*/ void social_conception(
1368  noble_being * female,
1369  noble_being * male,
1370  noble_simulation * sim)
1371 {
1372  if ((male == 0L) || (female == 0L))
1373  {
1374  return;
1375  }
1376 
1377  body_genetics(sim->beings, sim->num, being_fetal_genetics(female), being_genetics(female), being_genetics(male), female->seed);
1378 
1380  female->date_of_conception = sim->land->date;
1381 
1382  female->father_name[0] = being_gender_name(male);
1383  female->father_name[1] = being_first_name(male);
1384 
1385  if (male->generation_min < female->generation_min)
1386  {
1387  female->child_generation_min = male->generation_min;
1388  }
1389  else
1390  {
1391  female->child_generation_min = female->generation_min;
1392  }
1393 
1394  if (male->generation_max > female->generation_max)
1395  {
1396  female->child_generation_max = male->generation_max;
1397  }
1398  else
1399  {
1400  female->child_generation_max = female->generation_max;
1401  }
1402 
1404  being_reset_drive(female, DRIVE_SEX);
1406 
1407  female->goal[0]=GOAL_NONE;
1408  male->goal[0]=GOAL_NONE;
1409 
1411  episodic_interaction(sim, female, male, EVENT_MATE, (GENE_MATE_BOND(being_genetics(female))*AFFECT_MATE), 0);
1412  episodic_interaction(sim, male, female, EVENT_MATE, (GENE_MATE_BOND(being_genetics(male))*AFFECT_MATE), 0);
1413 }
1414 
1426  noble_being * meeter_being,
1427  noble_being * met_being,
1429  n_int distance,
1430  noble_simulation * sim)
1431 {
1432  n_int loc_state = 0;
1433  n_int attraction = 0;
1434  n_int attract;
1435 /* n_byte2 matingprob;*/
1436  noble_social * meeter_social_graph = being_social(meeter_being);
1437 
1438  if (!meeter_social_graph) return -1;
1439 
1440  /*if ((being_drive(meeter_being, DRIVE_SEX) > THRESHOLD_SEEK_MATE) &&
1441  (being_drive(met_being, DRIVE_SEX) > THRESHOLD_SEEK_MATE))*/
1442  {
1443 
1447  /*
1448 
1449  matingprob = being_random(meeter_being);
1450  if (matingprob <
1451  (32000 + (n_byte2)(met_being->honor)*
1452  GENE_STATUS_PREFERENCE(being_genetics(meeter_being))*MATING_PROB)) */
1453  {
1454 
1455 
1457  attraction = 1 +
1458  social_attraction_pheromone(meeter_being,met_being) +
1459  social_attraction_pigmentation(meeter_being,met_being) +
1460  social_attraction_height(meeter_being,met_being) +
1461  social_attraction_frame(meeter_being,met_being) +
1462  social_attraction_hair(meeter_being,met_being)
1463 #ifdef EPISODIC_ON
1464  + episodic_met_being_celebrity(sim,meeter_being,met_being)
1465 #endif
1466  ;
1467 
1469  /*if (meeter_social_graph[being_index].attraction > PAIR_BOND_THRESHOLD)
1470  {
1471  attraction++;
1472  */
1473  if (distance < MATING_RANGE)
1474  {
1476  being_immune_transmit(meeter_being, met_being, PATHOGEN_TRANSMISSION_SEX);
1477  being_immune_transmit(met_being, meeter_being, PATHOGEN_TRANSMISSION_SEX);
1479  if ((FIND_SEX(GET_I(meeter_being)) == SEX_FEMALE) &&
1480  (FIND_SEX(GET_I(met_being)) != SEX_FEMALE))
1481  {
1482  if (being_pregnant(meeter_being) == 0)
1483  {
1484  social_conception(meeter_being, met_being, sim);
1485  }
1486  }
1487  }
1488  /*
1489  }
1490  else
1491  {
1492  attraction--;
1493  }*/
1494  }
1495 
1496  attract = meeter_social_graph[being_index].attraction;
1497  if (attraction > 0)
1498  {
1499  if (attraction < PAIR_BOND_THRESHOLD*4)
1500  {
1501  if (attract < 255-attraction) attract+=attraction;
1502  }
1503  }
1504  else
1505  {
1506  if (attract > -attraction)
1507  {
1508  attract += attraction;
1509  }
1510  else
1511  {
1512  attract=0;
1513  }
1514  }
1515  meeter_social_graph[being_index].attraction=(n_byte)attract;
1516  }
1517  return loc_state;
1518 }
1519 
1528 static void social_chat_territory(
1529  noble_being * meeter_being,
1530  noble_being * met_being,
1532  noble_social * meeter_graph,
1533  n_uint respect_mean)
1534 {
1535 #ifdef TERRITORY_ON
1536  n_int idx=0,idx2,i=0,x,y;
1537 
1539  APESPACE_TO_TERRITORY(being_location_x(meeter_being));
1540  if (meeter_being->territory[idx].name==0)
1541  {
1542  i=0;
1543  for (y=-1; y<=1; y++)
1544  {
1545  for (x=-1; x<=1; x++)
1546  {
1547  if (!((x==0)&&(y==0)))
1548  {
1549  idx2 = idx + (y*TERRITORY_DIMENSION+x);
1550  if (idx2<0) idx2+=TERRITORY_AREA;
1551  if (idx2>=TERRITORY_AREA) idx2-=TERRITORY_AREA;
1552  i = meeter_being->territory[idx2].name;
1553  if (i>0)
1554  {
1555  y = 2;
1556  break;
1557  }
1558  }
1559  }
1560  }
1562  if (i == 0)
1563  {
1564  i = 1 + (n_byte)(being_random(meeter_being) & 255);
1565  }
1566  meeter_being->territory[idx].name = (n_byte)i;
1567  }
1568 
1570  if (meeter_graph[being_index].friend_foe >= respect_mean)
1571  {
1572  if (being_honor_compare(met_being, meeter_being) == 1)
1573  {
1574  if (met_being->territory[idx].name > 0)
1575  {
1576  meeter_being->territory[idx].name =
1577  met_being->territory[idx].name;
1578  }
1579  }
1580  else
1581  {
1582  if ((being_honor_compare(met_being, meeter_being) == -1) &&
1583  (meeter_being->territory[idx].name > 0))
1584  {
1585  met_being->territory[idx].name =
1586  meeter_being->territory[idx].name;
1587  }
1588  }
1589  }
1590 #endif
1591 }
1592 
1602  noble_being * meeter_being,
1603  noble_being * met_being,
1604  n_int being_index,
1605  noble_simulation * sim)
1606 {
1607  n_int idx,i=0;
1608  n_byte relationship_index;
1609  n_byte2 name, family;
1610  n_int replace;
1611  n_int speaking = 0;
1612  noble_social * meeter_graph = being_social(meeter_being);
1613  noble_social * met_graph = being_social(met_being);
1614  n_uint respect_mean = social_respect_mean(sim,meeter_being);
1615 
1616  if (!meeter_graph) return 0;
1617 
1618  if (!met_graph) return 0;
1619 
1621  social_chat_territory(meeter_being, met_being,being_index,meeter_graph,respect_mean);
1622 
1624  if ((meeter_graph[being_index].friend_foe) >= respect_mean)
1625  {
1626  episodic_interaction(sim, meeter_being, met_being, EVENT_CHAT, AFFECT_CHAT, 0);
1628  idx=-1;
1629  if (meeter_being->goal[0]==GOAL_MATE)
1630  {
1632  for (i=1; i<SOCIAL_SIZE_BEINGS; i++)
1633  {
1634  if (!SOCIAL_GRAPH_ENTRY_EMPTY(met_graph,i))
1635  {
1636  if ((met_graph[i].first_name[BEING_MET]==meeter_being->goal[1]) &&
1637  (met_graph[i].family_name[BEING_MET]==meeter_being->goal[2]))
1638  {
1639  idx=i;
1640  break;
1641  }
1642  }
1643  }
1644  }
1645  if (idx == -1)
1646  {
1648  relationship_index = GET_A(meeter_being,ATTENTION_RELATIONSHIP);
1649  if (relationship_index>0)
1650  {
1651  idx = social_get_relationship(meeter_being,relationship_index,sim);
1652  }
1653  else
1654  {
1656  idx = 1+(being_random(meeter_being)%(SOCIAL_SIZE_BEINGS-1));
1657  }
1658  }
1659 
1660  if (idx > -1)
1661  {
1663  name = met_graph[idx].first_name[BEING_MET];
1664  family = met_graph[idx].family_name[BEING_MET];
1665  if (!((name==0) && (family==0)))
1666  {
1667  for (i=1; i<SOCIAL_SIZE_BEINGS; i++)
1668  {
1669  if (!SOCIAL_GRAPH_ENTRY_EMPTY(meeter_graph,i))
1670  {
1671  if ((meeter_graph[i].first_name[BEING_MET]==name) &&
1672  (meeter_graph[i].family_name[BEING_MET]==family))
1673  {
1674  break;
1675  }
1676  }
1677  }
1678 
1679  if (i<SOCIAL_SIZE_BEINGS)
1680  {
1682  if (being_honor_compare(met_being, meeter_being) == 1)
1683  {
1684  meeter_graph[i].friend_foe++;
1685  }
1686  if (being_honor_compare(met_being, meeter_being) == -1)
1687  {
1688  meeter_graph[i].friend_foe--;
1689  }
1690  if (meeter_graph[i].familiarity < 65535) meeter_graph[i].familiarity++;
1691 
1693  if (spacetime_after(&met_graph[idx].space_time, &meeter_graph[i].space_time))
1694  {
1696  spacetime_copy(&meeter_graph[i].space_time, &met_graph[idx].space_time);
1697 
1699  meeter_graph[i].belief = met_graph[idx].belief;
1700  }
1701  speaking |= BEING_STATE_SPEAKING;
1702  }
1703  else
1704  {
1709  replace = get_stranger_link(meeter_being,met_being,sim);
1710  if (replace > -1)
1711  {
1712  io_copy((n_byte *)&met_graph[idx], (n_byte *)&meeter_graph[replace], sizeof(noble_social));
1713  meeter_graph[replace].attraction = 0;
1714  speaking |= BEING_STATE_SPEAKING;
1715 
1719  if (IS_FAMILY_MEMBER(met_graph,idx))
1720  {
1721  meeter_graph[replace].relationship =
1722  meeter_graph[replace].relationship+(OTHER_MOTHER-RELATIONSHIP_MOTHER);
1723  }
1724 #ifdef BRAINCODE_ON
1725 
1727  meeter_being,met_being,
1728  met_graph[idx].friend_foe,
1730 #endif
1731  }
1732  }
1733  }
1734  }
1735  }
1736  being_reset_drive(met_being, DRIVE_SOCIAL);
1737  being_reset_drive(meeter_being, DRIVE_SOCIAL);
1738 
1739 #ifdef BRAINCODE_ON
1741  sim,1,meeter_being,met_being,
1742  being_braincode_external(meeter_being),
1743  being_braincode_external(met_being),
1744  being_index);
1745 
1746 #endif
1747 #ifdef EPISODIC_ON
1748  social_group_align_preferences(
1749  sim,meeter_being,met_being,being_index);
1750 #endif
1751  if (speaking != 0)
1752  {
1753  being_add_state(meeter_being, BEING_STATE_SPEAKING);
1755  }
1756  return speaking;
1757 }
1758 
1766  noble_being * local)
1767 {
1768  n_int delta_x=0, delta_y=0, distsqr;
1769  n_byte2 goal;
1770  n_vect2 delta_vector,location_vector;
1771  goal = local->goal[0];
1772  switch(goal)
1773  {
1775  case GOAL_LOCATION:
1776  {
1777  if ((being_state(local) & BEING_STATE_SWIMMING) == 0)
1778  {
1779  vect2_byte2(&delta_vector, (n_byte2 *)&(local->goal[1]));
1780  vect2_byte2(&location_vector, being_location(local));
1781  vect2_subtract(&delta_vector, &location_vector, &delta_vector);
1782  being_facing_towards(local, &delta_vector);
1783  }
1784  break;
1785  }
1786  }
1787 
1789  if (goal==GOAL_LOCATION)
1790  {
1791  distsqr = delta_x*delta_x + delta_y*delta_y;
1792  if ((distsqr < GOAL_RADIUS) ||
1793  ((being_state(local) & BEING_STATE_SWIMMING) != 0))
1794  {
1796  local->goal[0] = GOAL_NONE;
1798  local->script_overrides -= OVERRIDE_GOAL;
1799  }
1800  }
1801 
1803  if (local->goal[3] > 0)
1804  {
1805  local->goal[3]--;
1806  }
1807  else
1808  {
1810  local->goal[0] = GOAL_NONE;
1811  }
1812 }
1813 
1814 void social_initial_loop(noble_simulation * local, noble_being * local_being, void * data)
1815 {
1816  n_uint respect_mean = social_respect_mean(local,local_being);
1817  n_uint social_loop = 0;
1818  n_vect2 location, sum_delta = {0,0};
1819  n_int familiar_being_count = 0;
1820  vect2_byte2(&location,(n_byte2 *)&(local_being->social_x));
1821  while ( social_loop < SOCIAL_SIZE_BEINGS )
1822  {
1823  noble_social * specific_individual = &(being_social(local_being)[social_loop]);
1824  noble_being * specific_being;
1825 
1826  if (!specific_individual) return;
1827 
1828  if (!SOCIAL_GRAPH_ENTRY_EMPTY(being_social(local_being),social_loop))
1829  {
1830  specific_being = being_find_name(local, specific_individual->first_name[BEING_MET], specific_individual->family_name[BEING_MET]);
1831 
1832  if (specific_being != 0L)
1833  {
1834  n_vect2 weighted_delta;
1835  n_vect2 familiar_location;
1836  n_int local_friend_or_foe = specific_individual->friend_foe;
1837  n_int distance_squared;
1838 
1839  local_friend_or_foe -= respect_mean;
1840 
1841  familiar_being_count++;
1842 
1843  vect2_byte2(&familiar_location,(n_byte2 *)&(specific_being->social_x));
1844 
1845  vect2_subtract(&weighted_delta, &familiar_location, &location);
1846 
1847  distance_squared = vect2_dot(&weighted_delta, &weighted_delta, 1, 512);
1848 
1849  if (distance_squared<0) distance_squared=0;
1851  vect2_d(&sum_delta,&weighted_delta, local_friend_or_foe * 2048,
1852  (distance_squared + 1));
1853  }
1854  }
1855 
1856  social_loop++;
1857  }
1858 
1859  if (familiar_being_count != 0)
1860  {
1861  vect2_d(&location,&sum_delta,1,(familiar_being_count*20));
1862  }
1863  vect2_back_byte2(&location,(n_byte2 *)&(local_being->social_nx));
1864 }
1865 
1871 void social_secondary_loop(noble_simulation * local, noble_being * local_being, void * data)
1872 {
1873  local_being->social_x = local_being->social_nx;
1874  local_being->social_y = local_being->social_ny;
1875 }