E motions sim

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
bluatigro
Posts: 660
Joined: Apr 25, 2012 10:35
Location: netherlands

E motions sim

Post by bluatigro »

you can use this to build a emotional AI

Code: Select all

type e_motion
  dim naam as string
  dim x as single
  dim y as single
  dim z as single
  declare constructor()
  declare constructor( n as string , nx as single , ny as single , nz as single )
  declare sub fill( n as string , nx as single , ny as single , nz as single )
  declare function move( e as integer , speed as single ) as e_motion
end type
constructor e_motion( )
  this.naam = ""
  this.x = 0
  this.y = 0
  this.z = 0
end constructor
constructor e_motion( n as string , nx as single , ny as single , nz as single )
  this.naam = n
  this.x = nx
  this.y = ny
  this.z = nz
end constructor
sub e_motion.fill( n as string , nx as single , ny as single , nz as single )
  this.naam = n
  this.x = nx
  this.y = ny
  this.z = nz
end sub
operator +( a as e_motion , b as e_motion ) as e_motion
  return type( "add" , a.x + b.x , a.y + b.y , a.z + b.z )
end operator
declare function dist( a as e_motion , b as e_motion ) as single
dim shared as e_motion emo( 13 )
dim shared as integer accepting , alert , anger , calm , disgust
dim shared as integer fear , happy , joy , sooted , sorrow
dim shared as integer suprise , tired , unhappy 
accepting = 0 : alert = 1 : anger = 2 : calm = 3
disgust = 4 : fear = 5 : happy = 6 : joy = 7
sooted = 8 : sorrow = 9 : suprise = 10 : tired = 11
unhappy = 12
emo( accepting ).fill "accepting", 0  , 8, 0  
emo( alert ).fill     "alert"    , 4  , 0, 0  
emo( anger ).fill     "anger"    , 3  ,-5, 3  
emo( calm ).fill      "calm"     , 0  , 0, 0  
emo( disgust ).fill   "disgust"  ,-1  ,-5, 0  
emo( fear ).fill      "fear"     , 3  , 5, 3  
emo( happy ).fill     "happy"    , 0  , 0, 8  
emo( joy ).fill       "joy"      , 2  , 0, 3  
emo( sooted ).fill    "sooted"   ,-3  , 0, 3  
emo( sorrow ).fill    "sorrow"   ,-2.5, 0,-3.5
emo( suprise ).fill   "suprise"  , 8  , 0, 0  
emo( tired ).fill     "tired"    ,-4  , 0, 0  
emo( unhappy ).fill   "unhappy"  , 0  , 0,-8  

declare sub smal()
declare sub big()
declare sub hug()
declare sub kick()
declare sub keepin()
declare function move( e as integer , a as single ) as e_motion
declare sub walk()

dim shared as e_motion nu , plus
dim shared as integer emonu

nu.fill "nu", 0 , 0 , 0


do
  cls
  print
  print 
  print "   i m : " ; emo( emonu ).naam
  print
  print "   1 = show smal spider ."
  print "   2 = show big spider ."
  print "   3 = give hug ."
  print "   4 = give kick ."
  print
  print "   esc = quit emotions simulation ."
  select case inkey
    case "1"
      smal
    case "2"
      big
    case "3"
      hug
    case "4"
      kick
    case else
      walk
  end select
  sleep 1000
loop while inkey <> chr( 27 )

sub walk
  plus.fill "add"  _
  , rnd( 0 ) * 4 - 2 _
  , rnd( 0 ) * 4 - 2 _
  , rnd( 0 ) * 4 - 2 
  keepin
end sub
sub smal()
  plus = nu.move( fear , 1 )
  keepin
end sub
sub big()
  plus = nu.move( fear , 2 )
  keepin
end sub
sub hug()
  plus = nu.move( happy , 1 )
  keepin
end sub
sub kick
  plus = nu.move( anger , 1 )
  keepin
end sub
function e_motion.move( e as integer , speed as single ) as e_motion
  dim as single d , dx , dy , dz
  d = dist( nu , emo( e ) )
  dx = emo( e ).x-nu.x
  dy = emo( e ).y-nu.y
  dz = emo( e ).z-nu.z
  return type( "add" _
  , dx*speed/d , dy*speed/d , dz*speed/d )
end function
sub keepin
  nu = nu + plus
  if nu.x >  8 then nu.x =  8
  if nu.x < -8 then nu.x = -8
  if nu.y >  8 then nu.y =  8
  if nu.y < -8 then nu.y = -8
  if nu.z >  8 then nu.z =  8
  if nu.z < -8 then nu.z = -8
  nu.fill "now" , nu.x , nu.y , nu.z 
  dim as single d , q
  dim as integer i
  d = 10
  emonu = 0
  for i = 0 to 12
    q = dist( emo( i ) , nu )
    if q < d then
      d = q
      emonu = i
    end if
  next i
end sub
function dist( a as e_motion , b as e_motion ) as single
  return sqr( ( a.x - b.x ) ^ 2 _
            + ( a.y - b.y ) ^ 2 _
            + ( a.z - b.z ) ^ 2 )
end function
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: E motions sim

Post by fxm »

Just a very small remark about the code syntax:

- In your code, the member Sub 'fill( n as string , nx as single , ny as single , nz as single )' has parameters and code identical to the constructor 'constructor( n as string , nx as single , ny as single , nz as single )'.

- Consequently, you can suppress the member Sub 'fill()' and replace all the calls 'instance.fill(...)' with 'instance = type(...)', which corresponds to a creation of temporary instance of 'e_motion'. Each created temporary instance is implicitly and automatically destroyed after use.


Your program modified as well:

Code: Select all

type e_motion
  dim naam as string
  dim x as single
  dim y as single
  dim z as single
  declare constructor()
  declare constructor( n as string , nx as single , ny as single , nz as single )
'  declare sub fill( n as string , nx as single , ny as single , nz as single )
  declare function move( e as integer , speed as single ) as e_motion
end type
constructor e_motion( )
  this.naam = ""
  this.x = 0
  this.y = 0
  this.z = 0
end constructor
constructor e_motion( n as string , nx as single , ny as single , nz as single )
  this.naam = n
  this.x = nx
  this.y = ny
  this.z = nz
end constructor
'sub e_motion.fill( n as string , nx as single , ny as single , nz as single )
'  this.naam = n
'  this.x = nx
'  this.y = ny
'  this.z = nz
'end sub
operator +( a as e_motion , b as e_motion ) as e_motion
  return type( "add" , a.x + b.x , a.y + b.y , a.z + b.z )
end operator
declare function dist( a as e_motion , b as e_motion ) as single
dim shared as e_motion emo( 13 )
dim shared as integer accepting , alert , anger , calm , disgust
dim shared as integer fear , happy , joy , sooted , sorrow
dim shared as integer suprise , tired , unhappy
accepting = 0 : alert = 1 : anger = 2 : calm = 3
disgust = 4 : fear = 5 : happy = 6 : joy = 7
sooted = 8 : sorrow = 9 : suprise = 10 : tired = 11
unhappy = 12
'emo( accepting ).fill "accepting", 0  , 8, 0 
'emo( alert ).fill     "alert"    , 4  , 0, 0 
'emo( anger ).fill     "anger"    , 3  ,-5, 3 
'emo( calm ).fill      "calm"     , 0  , 0, 0 
'emo( disgust ).fill   "disgust"  ,-1  ,-5, 0 
'emo( fear ).fill      "fear"     , 3  , 5, 3 
'emo( happy ).fill     "happy"    , 0  , 0, 8 
'emo( joy ).fill       "joy"      , 2  , 0, 3 
'emo( sooted ).fill    "sooted"   ,-3  , 0, 3 
'emo( sorrow ).fill    "sorrow"   ,-2.5, 0,-3.5
'emo( suprise ).fill   "suprise"  , 8  , 0, 0 
'emo( tired ).fill     "tired"    ,-4  , 0, 0 
'emo( unhappy ).fill   "unhappy"  , 0  , 0,-8 
emo( accepting ) = type( "accepting", 0  , 8, 0 )
emo( alert )     = type( "alert"    , 4  , 0, 0 )
emo( anger )     = type( "anger"    , 3  ,-5, 3 )
emo( calm )      = type( "calm"     , 0  , 0, 0 )
emo( disgust )   = type( "disgust"  ,-1  ,-5, 0 )
emo( fear )      = type( "fear"     , 3  , 5, 3 )
emo( happy )     = type( "happy"    , 0  , 0, 8 )
emo( joy )       = type( "joy"      , 2  , 0, 3 )
emo( sooted )    = type( "sooted"   ,-3  , 0, 3 )
emo( sorrow )    = type( "sorrow"   ,-2.5, 0,-3.5)
emo( suprise )   = type( "suprise"  , 8  , 0, 0 )
emo( tired )     = type( "tired"    ,-4  , 0, 0 )
emo( unhappy )   = type( "unhappy"  , 0  , 0,-8 )

declare sub smal()
declare sub big()
declare sub hug()
declare sub kick()
declare sub keepin()
declare function move( e as integer , a as single ) as e_motion
declare sub walk()

dim shared as e_motion nu , plus
dim shared as integer emonu

'nu.fill "nu", 0 , 0 , 0
nu = type( "nu", 0 , 0 , 0 )


do
  cls
  print
  print
  print "   i m : " ; emo( emonu ).naam
  print
  print "   1 = show smal spider ."
  print "   2 = show big spider ."
  print "   3 = give hug ."
  print "   4 = give kick ."
  print
  print "   esc = quit emotions simulation ."
  select case inkey
    case "1"
      smal
    case "2"
      big
    case "3"
      hug
    case "4"
      kick
    case else
      walk
  end select
  sleep 1000
loop while inkey <> chr( 27 )

sub walk
'  plus.fill "add"  _
'  , rnd( 0 ) * 4 - 2 _
'  , rnd( 0 ) * 4 - 2 _
'  , rnd( 0 ) * 4 - 2
  plus = type( "add"  _
  , rnd( 0 ) * 4 - 2 _
  , rnd( 0 ) * 4 - 2 _
  , rnd( 0 ) * 4 - 2 )
  keepin
end sub
sub smal()
  plus = nu.move( fear , 1 )
  keepin
end sub
sub big()
  plus = nu.move( fear , 2 )
  keepin
end sub
sub hug()
  plus = nu.move( happy , 1 )
  keepin
end sub
sub kick
  plus = nu.move( anger , 1 )
  keepin
end sub
function e_motion.move( e as integer , speed as single ) as e_motion
  dim as single d , dx , dy , dz
  d = dist( nu , emo( e ) )
  dx = emo( e ).x-nu.x
  dy = emo( e ).y-nu.y
  dz = emo( e ).z-nu.z
  return type( "add" _
  , dx*speed/d , dy*speed/d , dz*speed/d )
end function
sub keepin
  nu = nu + plus
  if nu.x >  8 then nu.x =  8
  if nu.x < -8 then nu.x = -8
  if nu.y >  8 then nu.y =  8
  if nu.y < -8 then nu.y = -8
  if nu.z >  8 then nu.z =  8
  if nu.z < -8 then nu.z = -8
'  nu.fill "now" , nu.x , nu.y , nu.z
  nu = type( "now" , nu.x , nu.y , nu.z )
  dim as single d , q
  dim as integer i
  d = 10
  emonu = 0
  for i = 0 to 12
    q = dist( emo( i ) , nu )
    if q < d then
      d = q
      emonu = i
    end if
  next i
end sub
function dist( a as e_motion , b as e_motion ) as single
  return sqr( ( a.x - b.x ) ^ 2 _
            + ( a.y - b.y ) ^ 2 _
            + ( a.z - b.z ) ^ 2 )
end function
Remark:
Instead of:
'instance = type(...)'
you could also use:
'instance = e_motion(...)'
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: E motions sim

Post by counting_pine »

I think it would be better just to have the constructor call fill().
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Re: E motions sim

Post by anonymous1337 »

I agree. Constructor code is only called once. As such, it's wise to have redundant code removed from the constructor, not from helper functions.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: E motions sim

Post by fxm »

My preferred solution is a single constructor without method 'fill', and each instance assignment by means of temporary type.

Code: Select all

type e_motion
  dim naam as string
  dim x as single
  dim y as single
  dim z as single
  declare constructor( n as string = "" , nx as single = 0 , ny as single = 0 , nz as single = 0 )
  declare function move( e as integer , speed as single ) as e_motion
end type
constructor e_motion( n as string = "" , nx as single = 0 , ny as single = 0 , nz as single = 0 )
  this.naam = n
  this.x = nx
  this.y = ny
  this.z = nz
end constructor
operator +( a as e_motion , b as e_motion ) as e_motion
  return type( "add" , a.x + b.x , a.y + b.y , a.z + b.z )
end operator
declare function dist( a as e_motion , b as e_motion ) as single
dim shared as e_motion emo( 13 )
dim shared as integer accepting , alert , anger , calm , disgust
dim shared as integer fear , happy , joy , sooted , sorrow
dim shared as integer suprise , tired , unhappy
accepting = 0 : alert = 1 : anger = 2 : calm = 3
disgust = 4 : fear = 5 : happy = 6 : joy = 7
sooted = 8 : sorrow = 9 : suprise = 10 : tired = 11
unhappy = 12
emo( accepting ) = type( "accepting", 0  , 8, 0 )
emo( alert )     = type( "alert"    , 4  , 0, 0 )
emo( anger )     = type( "anger"    , 3  ,-5, 3 )
emo( calm )      = type( "calm"     , 0  , 0, 0 )
emo( disgust )   = type( "disgust"  ,-1  ,-5, 0 )
emo( fear )      = type( "fear"     , 3  , 5, 3 )
emo( happy )     = type( "happy"    , 0  , 0, 8 )
emo( joy )       = type( "joy"      , 2  , 0, 3 )
emo( sooted )    = type( "sooted"   ,-3  , 0, 3 )
emo( sorrow )    = type( "sorrow"   ,-2.5, 0,-3.5)
emo( suprise )   = type( "suprise"  , 8  , 0, 0 )
emo( tired )     = type( "tired"    ,-4  , 0, 0 )
emo( unhappy )   = type( "unhappy"  , 0  , 0,-8 )

declare sub smal()
declare sub big()
declare sub hug()
declare sub kick()
declare sub keepin()
declare sub walk()

dim shared as e_motion nu , plus
dim shared as integer emonu

nu = type( "nu", 0 , 0 , 0 )


do
  cls
  print
  print
  print "   i m : " ; emo( emonu ).naam
  print
  print "   1 = show smal spider ."
  print "   2 = show big spider ."
  print "   3 = give hug ."
  print "   4 = give kick ."
  print
  print "   esc = quit emotions simulation ."
  select case inkey
    case "1"
      smal
    case "2"
      big
    case "3"
      hug
    case "4"
      kick
    case else
      walk
  end select
  sleep 1000
loop while inkey <> chr( 27 )

sub walk
  plus = type( "add"  _
  , rnd( 0 ) * 4 - 2 _
  , rnd( 0 ) * 4 - 2 _
  , rnd( 0 ) * 4 - 2 )
  keepin
end sub
sub smal()
  plus = nu.move( fear , 1 )
  keepin
end sub
sub big()
  plus = nu.move( fear , 2 )
  keepin
end sub
sub hug()
  plus = nu.move( happy , 1 )
  keepin
end sub
sub kick
  plus = nu.move( anger , 1 )
  keepin
end sub
function e_motion.move( e as integer , speed as single ) as e_motion
  dim as single d , dx , dy , dz
  d = dist( nu , emo( e ) )
  dx = emo( e ).x-nu.x
  dy = emo( e ).y-nu.y
  dz = emo( e ).z-nu.z
  return type( "add" _
  , dx*speed/d , dy*speed/d , dz*speed/d )
end function
sub keepin
  nu = nu + plus
  if nu.x >  8 then nu.x =  8
  if nu.x < -8 then nu.x = -8
  if nu.y >  8 then nu.y =  8
  if nu.y < -8 then nu.y = -8
  if nu.z >  8 then nu.z =  8
  if nu.z < -8 then nu.z = -8
  nu = type( "now" , nu.x , nu.y , nu.z )
  dim as single d , q
  dim as integer i
  d = 10
  emonu = 0
  for i = 0 to 12
    q = dist( emo( i ) , nu )
    if q < d then
      d = q
      emonu = i
    end if
  next i
end sub
function dist( a as e_motion , b as e_motion ) as single
  return sqr( ( a.x - b.x ) ^ 2 _
            + ( a.y - b.y ) ^ 2 _
            + ( a.z - b.z ) ^ 2 )
end function
bluatigro
Posts: 660
Joined: Apr 25, 2012 10:35
Location: netherlands

Re: E motions sim

Post by bluatigro »

taking al "lessons" into 1
i think this looks good to :

Code: Select all

type e_motion
  dim naam as string
  dim x as single
  dim y as single
  dim z as single
  declare constructor( n as string = "" , nx as single = 0 , ny as single = 0 , nz as single = 0 )
  declare function move( e as integer , speed as single ) as e_motion
end type
constructor e_motion( n as string = "" , nx as single = 0 , ny as single = 0 , nz as single = 0 )
  this.naam = n
  this.x = nx
  this.y = ny
  this.z = nz
end constructor
operator +( a as e_motion , b as e_motion ) as e_motion
  return type( "add" , a.x + b.x , a.y + b.y , a.z + b.z )
end operator
declare function dist( a as e_motion , b as e_motion ) as single
dim shared as e_motion emo( 13 )
dim shared as integer accepting , alert , anger , calm , disgust
dim shared as integer fear , happy , joy , sooted , sorrow
dim shared as integer suprise , tired , unhappy
accepting = 0 : alert = 1 : anger = 2 : calm = 3
disgust = 4 : fear = 5 : happy = 6 : joy = 7
sooted = 8 : sorrow = 9 : suprise = 10 : tired = 11
unhappy = 12
emo( accepting ) = e_motion( "accepting", 0  , 8, 0 )
emo( alert )     = e_motion( "alert"    , 4  , 0, 0 )
emo( anger )     = e_motion( "anger"    , 3  ,-5, 3 )
emo( calm )      = e_motion( "calm"     , 0  , 0, 0 )
emo( disgust )   = e_motion( "disgust"  ,-1  ,-5, 0 )
emo( fear )      = e_motion( "fear"     , 3  , 5, 3 )
emo( happy )     = e_motion( "happy"    , 0  , 0, 8 )
emo( joy )       = e_motion( "joy"      , 2  , 0, 3 )
emo( sooted )    = e_motion( "sooted"   ,-3  , 0, 3 )
emo( sorrow )    = e_motion( "sorrow"   ,-2.5, 0,-3.5)
emo( suprise )   = e_motion( "suprise"  , 8  , 0, 0 )
emo( tired )     = e_motion( "tired"    ,-4  , 0, 0 )
emo( unhappy )   = e_motion( "unhappy"  , 0  , 0,-8 )

declare sub smal()
declare sub big()
declare sub hug()
declare sub kick()
declare sub keepin()
declare sub walk()

dim shared as e_motion nu , plus
dim shared as integer emonu

nu = e_motion( "nu", 0 , 0 , 0 )

randomize timer

do
  cls
  print
  print
  print "   i feel / m : " ; emo( emonu ).naam
  print
  print "   1 = show smal spider ."
  print "   2 = show big spider ."
  print "   3 = give hug ."
  print "   4 = give kick ."
  print
  print "   esc = quit emotions simulation ."
  select case inkey
    case "1"
      smal
    case "2"
      big
    case "3"
      hug
    case "4"
      kick
    case else
      walk
  end select
  sleep 1000
loop while inkey <> chr( 27 )

sub walk
  plus = e_motion( "add"  _
  , rnd( 0 ) * 4 - 2 _
  , rnd( 0 ) * 4 - 2 _
  , rnd( 0 ) * 4 - 2 )
  keepin
end sub
sub smal()
  plus = nu.move( fear , 1 )
  keepin
end sub
sub big()
  plus = nu.move( fear , 2 )
  keepin
end sub
sub hug()
  plus = nu.move( happy , 1 )
  keepin
end sub
sub kick
  plus = nu.move( anger , 1 )
  keepin
end sub
function e_motion.move( e as integer , speed as single ) as e_motion
  dim as single d , dx , dy , dz
  d = dist( nu , emo( e ) )
  dx = emo( e ).x-nu.x
  dy = emo( e ).y-nu.y
  dz = emo( e ).z-nu.z
  return type( "add" _
  , dx*speed/d , dy*speed/d , dz*speed/d )
end function
sub keepin
  nu = nu + plus
  if nu.x >  8 then nu.x =  8
  if nu.x < -8 then nu.x = -8
  if nu.y >  8 then nu.y =  8
  if nu.y < -8 then nu.y = -8
  if nu.z >  8 then nu.z =  8
  if nu.z < -8 then nu.z = -8
  nu = e_motion( "now" , nu.x , nu.y , nu.z )
  dim as single d , q
  dim as integer i
  d = 10
  emonu = 0
  for i = 0 to 12
    q = dist( emo( i ) , nu )
    if q < d then
      d = q
      emonu = i
    end if
  next i
end sub
function dist( a as e_motion , b as e_motion ) as single
  return sqr( ( a.x - b.x ) ^ 2 _
            + ( a.y - b.y ) ^ 2 _
            + ( a.z - b.z ) ^ 2 )
end function
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: E motions sim

Post by fxm »

Each person may have a different opinion, but here's mine


The compiler accepts all the following syntaxes:

dim as e_motion simple1 = e_motion("", 0, 0, 0)

dim as e_motion simple2
simple2 = e_motion("", 0, 0, 0)

dim as e_motion simple3 = type<e_motion>("", 0, 0, 0)

dim as e_motion simple4
simple4 = type("", 0, 0, 0)



But personally, I prefer only use the two syntaxes in bold:

- When construction and assignment in a single line, call of constructor with the dedicated parameters.

- When in first construction (implicit constructor called automatically), then (second line) just assignment with a temporary instance.
why call a second time the constructor?
Post Reply