-------------------------- 
-- global script main -- 
-------------------------- 
 
-- View the generative process of an incestuous family-structure - depending on the Triangular  
-- structure between father, mother and child. 
-- King Oedipus was destined by fate to kill his father and take his mother as wife. 
 
global theWorld 
 
 
on prepareMovie 
  tabulaRasa() 
end 
 
 
on startMovie 
  theWorld.genesis()  
end 
 
 
on tabulaRasa 
  clearglobals 
  member("out").text = "a man and a woman..." 
   
  the actorlist = [] 
   
  -- a non-interactive world  
  theWorld = new(script("theWorld")) 
end 
 
 
on print str 
  if member("out").line.count < 4 then 
    member("out").line[member("out").line.count + 1] = str 
  else  
    member("out").line[1].delete() 
    member("out").line[4] = str 
  end if    
end 
 
 
 
------------------------------ 
-- the world and its gods ---- 
-- parent script theWorld -- 
------------------------------ 
 
property myVisual 
property population 
property dynasticFemaleCount 
property dynasticMaleCount 
property mist 
property popImages 
 
 
-- big bang 
on new theWorld 
  population = [] 
  dynasticFemaleCount = 0 
  dynasticMaleCount = 0 
   
  -- visualization 
  myVisual = (the stage).image 
   
  -- the veil of oblivion  
  mist = image(10,10,32
  mist.fill(0,0,10,10,rgb(255,255,255)) 
   
  -- the beings visual representation 
  popImages = [member("o0").image, member("o1").image, member("o2").image, member("i0").image, member("i1").image, member("i2").image
   
  (the actorlist).append(theWorld) 
   
  return theWorld 
end 
 
 
-- something like adam & eve.  
-- the complete harmony between wife and husband. 
on genesis theWorld 
  centerOfTheUniverse = point(theWorld.myVisual.width / 2, theWorld.myVisual.height / 2
  -- first male 
  population[1] = new(script("oedipus"), point(random(400), random(400)), void, void)   
  -- first female 
  population[2] = new(script("jocasta"),  centerOfTheUniverse, void, void
end 
 
 
 
on stepFrame theWorld  
  -- as days go by, memories vanish 
  -- Ego is sufficiently strong to suppress unconscious urges.  
  theWorld.forgets() 
  whoMeetsOne() 
end 
 
 
-- female number ...  
on dynasticFemale theWorld 
  dynasticFemaleCount = dynasticFemaleCount + 1 
   
  return(dynasticFemaleCount) 
end 
 
 
-- male number ... 
on dynasticMale theWorld 
  dynasticMaleCount = dynasticMaleCount + 1 
   
  return(dynasticMaleCount) 
end 
 
 
-- as people go along, they might meet someone 
on whoMeetsOne theWorld 
  repeat with i = population.count down to 1 
    person1 = population[i] 
    if i > 1 then 
      repeat with j = i - 1 down to 1 
        person2 = population[j] 
         
        -- do they meet? 
        if abs(person1.myCenter[1] - person2.myCenter[1]) < 10 and abs(person1.myCenter[2] - person2.myCenter[2]) < 10 then 
           
          -- same sex? 
          if person1.myName.char[1] = person2.myName.char[1] then 
            person1.greets(person2) 
             
            -- different sex, ... 
          else 
            person1.letsHaveSex(person2) 
            person2.letsHaveSex(person1) 
          end if 
        end if 
      end repeat 
    end if 
  end repeat 
end 
 
 
-- new being gets born, if it's not already too crowded 
on wonderOfBirth theWorld, mummy, daddy 
  -- this world doesn't support more than 50 inhabitants :) 
  if population.count < 51 then 
    if isItaBoy() then 
      newBeing = new(script("oedipus"), mummy.myCenter, mummy, daddy) 
    else 
      newBeing = new(script("jocasta"), mummy.myCenter, mummy, daddy) 
    end if 
    population.append(newBeing) 
     
    return newBeing 
  else 
    return void 
  end if    
end 
 
 
-- some regulation: more females -> boys get born // more males -> girls 
on isItABoy theWorld 
  boyProbability = random(dynasticFemaleCount * 100
  girlProbability = random(dynasticMaleCount * 100
  if boyProbability >= girlProbability then 
    return true 
  else 
    return false 
  end if 
end 
 
 
-- visualization 
on link theWorld, related1, related2 
  myVisual.draw(related1.myCenter, related2.myCenter, [#shapeType:#line, #lineSize: 1, #color: rgb(100,100,100)])  
end 
 
 
-- show the beings 
on represent theWorld, pos, img, col 
  myVisual.copyPixels(popImages[img], rect(-7 + pos[1], -7 + pos[2], 7 + pos[1], 7 + pos[2]), rect(0,0,14,14), [#ink:36, #color: col]) 
end 
 
 
-- the veil of oblivion  
on forgets theWorld 
  myVisual.copyPixels(mist, rect(0,0,400,400), mist.rect, [#blendLevel: 70]) 
end 
 
 
 
--------------------------------------------- 
-- prototype of the world's male inhabitant -- 
-- parent script oedipus ------------------ 
--------------------------------------------- 
 
--what i know 
global theWorld 
 
property myName 
property myCenter 
property myAge 
property myMaritalStatus 
property myDad 
property myMum 
property myWife 
property myKids 
 
-- movementData roaming 
property myExile 
property myStepsToExile 
property myStepsToExileDone 
property myOrigin 
 
-- movement circles 
property myDistance 
property myMaxDistance, myMinDistance 
property myAttraction 
property myAngle 
 
-- visual representation 
property myColor 
 
 
 
-- oedipus gets born 
on new oedipus, whereIWasBorn, mummy, daddy 
  -- A character with a mixture of good and evil is more compelling than a character who is merely good.  
  -- And Oedipus is definitely not perfect.   
   
  -- what's my dynastic number, actually there are a few more oedipussi around 
  numberX = theWorld.dynasticMale() 
  myName = "Oedipus" && string(numberX) 
   
  myColor = rgb(10,10,min(numberX * 7, 255)) 
   
  myMum = mummy 
  myDad = daddy 
  myWife = void 
  myKids = [] 
  myAge = 0 
   
  -- first being? 
  if myDad = void then  
    myMaritalStatus = #single 
  else 
    myMaritalStatus = #kid 
  end if 
   
  myCenter = whereIWasBorn 
  -- my mother is still there...;) 
   
  myExile = myCenter 
   
  newTarget() 
   
  (the actorlist).append(oedipus) 
   
  print(myName && "was born."
   
  return oedipus 
end 
 
 
-- day by day 
on stepFrame oedipus 
  if myMaritalStatus = #married then 
    goCircles() 
  else 
    roamAround() 
    -- searching for something ? 
  end if 
   
  -- family tree (mama, papa, child) 
  if myMum <> void then theWorld.link(oedipus, myMum) 
  if myDad <> void then theWorld.link(oedipus, myDad) 
   
  oedipus.visualize() 
end 
 
 
-- married man do so 
on goCircles oedipus 
  myDistance = myDistance + myAttraction 
   
  if myDistance > myMaxDistance and myAttraction > 0 then 
    myAttraction = random(50) / -50.0 
    myMinDistance = random(20
  else if myDistance < myMinDistance and myAttraction < 0 then 
    myAttraction = random(50) / 50.0 
    myMaxDistance = random(130
  end if 
  myAngle = myAngle + pi / 150 
  myCenter = myWife.myCenter + point(sin(myAngle), cos(myAngle)) * myDistance 
end 
 
 
on newAttraction oedipus 
  myMinDistance = 1.0 
  myDistance = 20.0 
  myAngle = (200.0 / random(100)) * pi 
  myAttraction = random(50) / 50.0 
  myMaxDistance = random(130
end 
 
 
-- life without direction, he has no chance to change the destiny that fate has in store for him 
on roamAround oedipus 
  myStepsToExileDone = myStepsToExileDone + 1 
  if myStepsToExileDone < myStepsToExile then 
    myCenter = myOrigin + ((myExile - myOrigin) / myStepsToExile) * myStepsToExileDone 
  else 
    newTarget() 
  end if 
end 
 
 
-- find something new? 
on newTarget oedipus 
  -- getting older 
  myAge = myAge + 6 
  -- it is time to realize that he develops love for his mother.  
  -- but what a pity - his mother loves his father. 
  if myAge > 15 and myMaritalStatus = #kid then myMaritalStatus = #immature 
  myCenter = myExile 
  myOrigin = myCenter 
  myExile = point(float(random(400)), float(random(400))) 
  myStepsToExile = random(50) + 30 
  myStepsToExileDone = 0 
end 
 
 
-- free? 
-- oedipus begins to see the father, the love-object of the mother, as a rival.  
-- Culminating in a desire to get rid of him. 
on killDaddy oedipus 
  print(myName && "kills his dad" && myDad.myName) 
   
  myDad.iDie() 
  myMaritalStatus = #single  
end 
 
 
-- who killed me? 
on iDie oedipus 
  print(myname && "dies!!!!"
   
  -- tell them I'm dead 
  if myWife <> void then 
    myWife.myMaritalStatus = #single 
    myWife.myHusband = void 
  end if 
   
  -- my dad is dead already... 
   
  if myMum <> void then 
    myMum.myKids.deleteOne(oedipus) 
  end if 
   
  if myKids.count > 0 then 
    repeat with i = 1 to myKids.count 
      myKids[i].myDad = void 
      -- losing control over my sons 
      if myKids[i].myName contains "Oedipus" then myKids[i].myMaritalStatus = #single 
    end repeat 
  end if 
   
  theWorld.population.deleteOne(oedipus) 
  (the actorlist).deleteOne(oedipus) 
end   
 
 
-- two males meet 
on greets oedipus, otherOne 
  if otherOne = myDad and myMaritalStatus = #immature then  
    oedipus.killDaddy() 
  else 
    --print(aren't we related?) 
  end if     
end 
 
 
 
on letsHaveSex oedipus, newWife 
  -- old enough? 
  if (myMaritalStatus = #single or myMaritalStatus = #married) and
(newWife.myMaritalStatus = #single or newWife.myMaritalStatus = #married) then 
    if newWife <> myWife and myMaritalStatus = #married then 
      -- getting divorced from my old wife 
      myWife.myMaritalStatus = #single 
    end if 
     
    myWife = newWife 
    -- she is realy pretty 
    myMaritalStatus = #married 
    newAttraction() 
  end if 
end 
 
 
-- show me on screen 
on visualize oedipus, col 
  case myMaritalStatus of 
    #married: 
      img = 3 
    #single: 
      img = 2 
    #immature, #kid: 
      img = 1 
  end case   
   
  theWorld.represent(myCenter, img, myColor)  
end 
 
 
 
----------------------------------------------- 
-- prototype of the worlds female inhabitant -- 
-- parent script jocasta -------------------- 
----------------------------------------------- 
 
global theWorld 
 
property myName 
property myPlaceOfBirth -- my mother is still there ...;) 
property myCenter 
property myAge 
property myMaritalStatus -- various combinations are possible like mother-son and father-daughter 
property myMum, myDad -- who actually is my real father/mother ? 
property myHusband -- who is my husband at the moment ? 
property myKids 
 
-- movementData 
property myAngle 
property myRadius 
property myAttraction 
property myMaxDistance -- how far does a wife get? 
 
-- visual representation 
property myColor 
 
 
-- jocasta gets born 
on new jocasta, whereIwasBorn, mummy, daddy, theWorld 
  -- what's my dynastic number 
  numberX = theWorld.dynasticFemale() 
  myName = "Iocasta" && string(numberX) 
   
  myColor = rgb(min(numberX * 7, 255),10,10
   
  myMum = mummy 
  myDad = daddy 
  myKids = [] 
  myAge = 0 
   
  -- first being? 
  if myMum = void then  
    myMaritalStatus = #single 
  else 
    myMaritalStatus = #immature 
    -- my husband has to be like my father 
  end if 
   
  myPlaceOfBirth = whereIwasBorn 
  myCenter = myPlaceOfBirth 
  visualize(jocasta) 
   
  -- movement 
  myAngle = (2 * pi) / 100 * random(100
  myMaxDistance = random(100
  myAttraction = #theWorld 
   
  (the actorlist).append(jocasta) 
   
  print(myName && "was born."
   
  return jocasta 
end 
 
 
-- day by day 
on stepFrame jocasta 
  if myMaritalStatus = #single or myMaritalStatus = #immature then seeALittleLife() 
  if myMaritalStatus = #married then stayHome() 
   
  -- family tree (mama, papa, child) 
  if myMum <> void then theWorld.link(jocasta, myMum) 
  if myDad <> void then theWorld.link(jocasta, myDad) 
  if myHusband <> void then theWorld.link(jocasta, myHusband) 
   
  jocasta.visualize() 
end 
 
 
on stayHome jocasta 
  -- do nothing or some housework 
end 
 
 
on jealousToDeath jocasta 
  -- my husband had sex with my daughter - son of a bitch! 
  print(myName && "is scared to death by her husbands shameful action"
  jocasta.iDie() 
end 
 
 
on iDie jocasta 
  print(myname  && "dies!!!!"
   
  -- tell them I'm dead 
  if myHusband <> void then  
    myHusband.myMaritalStatus = #single 
    myHusband.myWife = void 
  end if 
   
  if myDad <> void then myDad.myKids.deleteOne(jocasta) 
   
  if myMum <> void then myMum.myKids.deleteOne(jocasta) 
   
  if myKids.count > 0 then 
    repeat with i = 1 to myKids.count 
      myKids[i].myMum = void 
    end repeat 
  end if 
   
  theWorld.population.deleteOne(jocasta) 
  (the actorlist).deleteOne(jocasta) 
end   
 
 
-- scan the world around home 
on seeALittleLife jocasta 
  if myAttraction = #theWorld then 
    myRadius = myRadius + random(5
    if myRadius > myMaxDistance then  
      myAttraction = #home 
      myAge = myAge + 5 
      if myAge > 15 and myMaritalStatus = #immature then myMaritalStatus = #single 
    end if 
  else 
    myRadius = myRadius - random(5
    if myRadius < 0 then 
      myRadius = 0 
      myAttraction = #theWorld 
      myMaxDistance = random(150
    end if 
  end if 
  myAngle = myAngle - pi / 100 
   
  myCenter = myPlaceOfBirth + point(sin(myAngle), cos(myAngle)) * myRadius 
end 
 
 
on greets jocasta, otherName 
  -- print(myName && greetz && otherName & : arent't we related?) 
end 
 
 
on letsHaveSex jocasta, newDaddy 
  -- old enough? 
  if myMaritalStatus = #immature then 
    -- print(kid && myName && meets && newDaddy.myName & .) 
  else if newDaddy.myMaritalStatus = #single or newDaddy.myMaritalStatus = #married then 
    myMaritalStatus = #married 
     
    -- is it papa? 
    if newDaddy = myDad then 
      if myMum <> void then 
        -- mum got a serious problem 
        myMum.jealousToDeath() 
      end if 
      print(myName && "has sex with her daddy" && newDaddy.myName & "."
    else if myHusband = newDaddy then 
      print(myName && "is having sex with her husband" && newDaddy.myName & "."
    else 
      print(myName && "has sex with" && newDaddy.myName & "."
      if myHusband <> void then  
        -- getting divorced 
        myHusband.myMaritalStatus = #single 
      end if 
    end if 
    myHusband = newDaddy 
     
    newKid = theWorld.wonderOfBirth(jocasta, myHusband) 
     
    if newKid <> void then 
      myKids.append(newKid) 
      newDaddy.myKids.append(newKid) 
    end if 
  end if 
end 
 
 
-- show me on screen 
on visualize jocasta 
  case myMaritalStatus of 
    #married: 
      img = 6 
    #single: 
      img = 5 
    #immature: 
      img = 4 
  end case 
     
  theWorld.represent(myCenter, img, myColor)  
end 
 
 
 
------------------------------------ 
-- frame script andOnAndOnAndOn -- 
------------------------------------ 
 
property visualMove 
 
-- new day raising 
on exitFrame me 
  visualMove = (visualMove + 1) mod 15 
  sprite(1).locH = visualMove - 15 
   
  go the frame 
end 




Note: You can download Pedigree here as uncompiled Director movie.

launch project

artists' comments