/// <summary> /// Transforms FML into BML and executes /// </summary> /// <param name="body">the FML body containing the FML functions to be interpreted</param> private void interpret(FMLBody body) { foreach (var chunk in body.chunks) { BMLBody curr = new BMLBody(); chunk.BMLRef = curr; foreach (var function in chunk.functions) { Vocalisation voc = new Vocalisation("Vocal", chunk.owner, 1f, mood.GetArousal(), mood.GetValence()); switch (function.Function) { case FMLFunction.FunctionType.BOARDGAME_REACT_MOVE: ReactMoveFunction react = function as ReactMoveFunction; this.react(react.MoveToReact[0], react.MyMove ? player : (player == Player.First ? Player.Second : Player.First)); FaceEmotion faceReact; Posture poser = new Posture("postureReact", chunk.owner, Behaviour.Lexemes.Stance.SITTING, 0f, 8f); if (surprised.Check()) { int coin = UnityEngine.Random.Range(0, 3); faceReact = new FaceEmotion("ConfusedFace", chunk.owner, 0f, 1.4f * expressionIntensity, 0.8f * expressionIntensity); if (coin < 2) { poser.AddPose(Behaviour.Lexemes.BodyPart.RIGHT_ARM, Behaviour.Lexemes.BodyPose.FIST_COVER_MOUTH); curr.AddChunk(poser); } coin = UnityEngine.Random.Range(0, noiseChance); curr.AddChunk(faceReact); if (coin == 0) curr.AddChunk(voc); } break; case FMLFunction.FunctionType.BOARDGAME_CONSIDER_MOVE: //tbh this shouldn't be here if (impatient.Check()) { Debug.Log("IMPATIENT"); Gaze glanceAtPlayer = new Gaze("glanceAtPlayer", chunk.owner, motion.Player, Behaviour.Lexemes.Influence.HEAD, start: 0f, end: 0.25f, priority: 2); curr.AddChunk(glanceAtPlayer); curr.AddChunk(voc); } else { ConsiderMoveFunction func = function as ConsiderMoveFunction; if (func.MoveToConsider.Type == MoveType.MOVE) { Gaze glanceFrom = new Gaze("glanceAtFrom", chunk.owner, BoardgameManager.Instance.GetCellObject(func.MoveToConsider.From), Behaviour.Lexemes.Influence.HEAD, start: 0f, end: 2f); curr.AddChunk(glanceFrom); Gaze glanceTo = new Gaze("glanceAtTo", chunk.owner, BoardgameManager.Instance.GetCellObject(func.MoveToConsider.To), Behaviour.Lexemes.Influence.HEAD, start: 2.1f, end: 2f, priority: 2); curr.AddChunk(glanceTo); } else { Gaze glanceTo = new Gaze("glanceAtCell", chunk.owner, BoardgameManager.Instance.GetCellObject(func.MoveToConsider.To), Behaviour.Lexemes.Influence.HEAD, start: 0f, end: 2f); curr.AddChunk(glanceTo); } } break; case FMLFunction.FunctionType.BOARDGAME_MAKE_MOVE: MakeMoveFunction move = function as MakeMoveFunction; PhysicalCell from, to; BoardgameManager.Instance.GetMoveFromTo(move.MoveToMake[0], player, out from, out to); Grasp reach = new Grasp("reachTowardsPiece", chunk.owner, from.gameObject, Behaviour.Lexemes.Mode.LEFT_HAND, (arm) => { graspPiece(from, arm); }, 0, end: 1.5f); Posture leanReach = new Posture("leantowardsPiece", chunk.owner, Behaviour.Lexemes.Stance.SITTING, 0, end: 1.5f, priority: 2); Gaze lookReach = new Gaze("glanceAtReach", chunk.owner, from.gameObject, Behaviour.Lexemes.Influence.HEAD, start: 0f, end: 1.25f); Debug.Log((int)(Vector3.Distance(from.transform.position, transform.position) * 40)); leanReach.AddPose(Behaviour.Lexemes.BodyPart.WHOLEBODY, Behaviour.Lexemes.BodyPose.LEANING_FORWARD, (int)(Vector3.Distance(from.transform.position, transform.position) * 40)); Place place = new Place("placePiece", chunk.owner, to.gameObject, Behaviour.Lexemes.Mode.LEFT_HAND, (piece) => { placePiece(piece, to); BoardgameManager.Instance.MoveMade(move.MoveToMake, player); BoardgameManager.Instance.SyncState(); BoardgameManager.Instance.MakeNoise(to.id); }, 1.25f, end: 2f); Posture leanPlace = new Posture("leantowardsCell", chunk.owner, Behaviour.Lexemes.Stance.SITTING, 1.25f, end: 1.5f, priority: 3); leanPlace.AddPose(Behaviour.Lexemes.BodyPart.WHOLEBODY, Behaviour.Lexemes.BodyPose.LEANING_FORWARD, (int)(Vector3.Distance(to.transform.position, transform.position) * 40)); Gaze lookPlace = new Gaze("glanceAtPlace", chunk.owner, to.gameObject, Behaviour.Lexemes.Influence.HEAD, start: 1.25f, end: 2f, priority: 2); Gaze glance = new Gaze("glanceAtPlayer", chunk.owner, motion.Player, Behaviour.Lexemes.Influence.HEAD, start: 2f, end: 1.25f, priority: 3); curr.AddChunk(glance); curr.AddChunk(lookReach); curr.AddChunk(lookPlace); curr.AddChunk(leanReach); curr.AddChunk(leanPlace); curr.AddChunk(reach); curr.AddChunk(place); break; case FMLFunction.FunctionType.EMOTION: //transform expression EmotionFunction f = function as EmotionFunction; float v = Mathf.Clamp(f.Valence, 0, 2); if (v < Config.Neutral) { v = (v - Config.Neutral) * 0.8f + Config.Neutral; } float a = Mathf.Clamp(f.Arousal, 0, 2); if (a > Config.Neutral) { a = (a - Config.Neutral) * 0.6f + Config.Neutral; } FaceEmotion fe = new FaceEmotion("emote " + f.Arousal + " " + f.Valence, chunk.owner, 0f, a, v); float lean = Mathf.Clamp((f.Arousal - Config.Neutral) * 30, -20, 30); Posture emoLean = new Posture("emoteLean", chunk.owner, Behaviour.Lexemes.Stance.SITTING, 0, end: 3f); emoLean.AddPose(Behaviour.Lexemes.BodyPart.WHOLEBODY, Behaviour.Lexemes.BodyPose.LEANING_FORWARD, (int)lean); curr.AddChunk(emoLean); curr.AddChunk(fe); break; } } } //sort out timing foreach (var chunk in body.chunks) { if (chunk.timing != null) { switch (chunk.timing.Primitive) { case Primitive.MustEndBefore: chunk.timing.ChunkReference.BMLRef.ExecuteAfter(chunk.BMLRef); break; case Primitive.StartImmediatelyAfter: chunk.BMLRef.ExecuteAfter(chunk.timing.ChunkReference.BMLRef); break; } } } //let's refactor this later so that we don't have to do 3N foreach (var chunk in body.chunks) { behave.ScheduleBehaviour(chunk.BMLRef); } }