# -*- coding: utf-8 -*- """Non-transitive dice: A beats B, B beats C and C beats A, always 5 out of 9.""" import sys, os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from manim import * from tiktok import * RED_C = C_PINK FACES = {"rojo": [2, 4, 9], "celeste": [1, 6, 8], "verde": [3, 5, 7]} COL = {"rojo": RED_C, "celeste": C_SKY, "verde": C_GREEN} CELL = 1.30 def die(obj_name, s=0.62): vals = FACES[obj_name] * 2 col = COL[obj_name] face_list = VGroup() for v in vals: f = RoundedRectangle(corner_radius=0.11, width=s, height=s, stroke_width=3, stroke_color=col, fill_color="#121C33", fill_opacity=1) face_list.add(VGroup(f, Text(str(v), font=FONT, font_size=32, weight=BOLD, color=col).move_to(f))) face_list.arrange_in_grid(rows=2, cols=3, buff=0.08) rot = Text(obj_name, font=FONT, font_size=30, weight=BOLD, color=col) rot.next_to(face_list, DOWN, buff=0.18) return VGroup(face_list, rot) def duel(na, nb, center_pt): """3x3 table with the nine duels. Each cell painted with the winner's color.""" av, bv = FACES[na], FACES[nb] ca, cb = COL[na], COL[nb] cells, wins = VGroup(), 0 for i, a in enumerate(av): for j, bq in enumerate(bv): ok = a > bq wins += ok r = RoundedRectangle(corner_radius=0.1, width=CELL, height=CELL, stroke_width=4, stroke_color="#0B0F1A", fill_color=ca if ok else cb, fill_opacity=0.92) t = Text(str(max(a, bq)), font=FONT, font_size=42, weight=BOLD, color="#0B0F1A") c = VGroup(r, t.move_to(r)) c.move_to(center_pt + np.array([(j - 1) * (CELL + 0.07), -(i - 1) * (CELL + 0.07), 0.0])) cells.add(c) d = CELL + 0.07 outside = d + CELL / 2 + 0.36 # the caption goes outside the table header = VGroup(*[Text(str(v), font=FONT, font_size=38, weight=BOLD, color=cb) .move_to(center_pt + np.array([(j - 1) * d, outside, 0.0])) for j, v in enumerate(bv)]) lat = VGroup(*[Text(str(v), font=FONT, font_size=38, weight=BOLD, color=ca) .move_to(center_pt + np.array([-outside, -(i - 1) * d, 0.0])) for i, v in enumerate(av)]) return cells, header, lat, wins class Dice(TikTok): NAME = "dados" def construct(self): self.prepare() chip = self.chip("Intuición rota", RED_C) dds = VGroup(*[die(n) for n in ("rojo", "celeste", "verde")]) dds.arrange(RIGHT, buff=0.55).move_to(UP * 4.15) with self.beat(0) as b: b.play(FadeIn(chip, shift=DOWN * 0.3), run_time=0.4) b.play(LaggedStart(*[FadeIn(d, shift=DOWN * 0.3) for d in dds], lag_ratio=0.25), run_time=1.1) finger = Triangle(stroke_width=0, fill_color=WHITE, fill_opacity=1).scale(0.22) finger.rotate(PI).next_to(dds[1], DOWN, buff=0.35) b.play(FadeIn(finger, shift=UP * 0.3), run_time=0.5) you_side = Text("vos", font=FONT, font_size=34, weight=BOLD, color=WHITE) you_side.next_to(finger, DOWN, buff=0.15) me_txt = Text("yo elijo después", font=FONT, font_size=40, weight=BOLD, color=AMBER) me_txt.move_to(UP * 1.45) with self.beat(1) as b: b.play(FadeIn(you_side), run_time=0.35) b.play(FadeIn(me_txt, shift=UP * 0.2), run_time=0.6) big_txt = Text("56%", font=FONT, font_size=190, weight=BOLD, color=AMBER) big_txt.move_to(DOWN * 0.55) footer = Text("gano yo", font=FONT, font_size=46, weight=BOLD, color=WHITE) footer.next_to(big_txt, DOWN, buff=0.25) with self.beat(2) as b: b.play(FadeOut(VGroup(finger, you_side, me_txt)), run_time=0.3) b.play(FadeIn(big_txt, scale=0.6), run_time=0.7) b.play(FadeIn(footer, shift=UP * 0.2), run_time=0.4) b.play(Flash(big_txt, color=AMBER, flash_radius=2.6, num_lines=20), run_time=0.8) with self.beat(3) as b: b.play(FadeOut(VGroup(big_txt, footer)), run_time=0.35) b.play(dds[1].animate.set_opacity(0.25), dds[2].animate.set_opacity(0.25), run_time=0.4) big_one = dds[0].copy().scale(2.0).move_to(UP * 1.2) b.play(TransformFromCopy(dds[0], big_one), run_time=0.8) with self.beat(4) as b: b.play(FadeOut(big_one), dds[1].animate.set_opacity(1), dds[2].animate.set_opacity(1), run_time=0.5) g2 = dds[1].copy().scale(1.7).move_to(UP * 1.5 + LEFT * 1.9) g3 = dds[2].copy().scale(1.7).move_to(UP * 1.5 + RIGHT * 1.9) b.play(TransformFromCopy(dds[1], g2), run_time=0.6) b.play(TransformFromCopy(dds[2], g3), run_time=0.6) # --- the three match-ups ------------------------------------------------ center_pt = np.array([0.0, 0.42, 0.0]) def crossing(beat, na, nb, previous): cells, header, lat, wins = duel(na, nb, center_pt) tick_m = VGroup( Text(na, font=FONT, font_size=42, weight=BOLD, color=COL[na]), Text(f"gana {wins} de 9", font=FONT, font_size=42, weight=BOLD, color=WHITE), ).arrange(RIGHT, buff=0.25).move_to(DOWN * 2.45) if previous: beat.play(FadeOut(previous), run_time=0.3) beat.play(FadeIn(VGroup(header, lat)), run_time=0.35) beat.play(LaggedStart(*[FadeIn(c, scale=0.6) for c in cells], lag_ratio=0.09), run_time=max(1.0, beat.floor - 1.5)) beat.play(FadeIn(tick_m, shift=UP * 0.2), run_time=0.45) return VGroup(cells, header, lat, tick_m) with self.beat(5) as b: b.play(FadeOut(VGroup(g2, g3)), run_time=0.3) t1 = crossing(b, "rojo", "celeste", None) with self.beat(6) as b: t2 = crossing(b, "celeste", "verde", t1) with self.beat(7) as b: b.play(FadeOut(t2), run_time=0.35) question = VGroup( Text("rojo", font=FONT, font_size=54, weight=BOLD, color=RED_C), Text("→", font=FONT, font_size=54, weight=BOLD, color=WHITE), Text("verde", font=FONT, font_size=54, weight=BOLD, color=C_GREEN), Text("?", font=FONT, font_size=70, weight=BOLD, color=AMBER), ).arrange(RIGHT, buff=0.3).move_to(UP * 1.6) b.play(FadeIn(question, shift=UP * 0.25), run_time=0.6) b.play(Indicate(question[3], color=AMBER, scale_factor=1.4), run_time=0.7) with self.beat(8) as b: no = Text("NO", font=FONT, font_size=96, weight=BOLD, color=C_PINK).move_to(UP * 1.6) b.play(FadeOut(question), run_time=0.25) b.play(FadeIn(no, scale=1.8), run_time=0.4) b.play(FadeOut(no), run_time=0.3) t3 = crossing(b, "verde", "rojo", None) # --- the circle ---------------------------------------------------------- with self.beat(9) as b: b.play(FadeOut(t3), FadeOut(dds), run_time=0.4) vert = {"rojo": np.array([0.0, 4.1, 0.0]), "celeste": np.array([-2.55, 0.5, 0.0]), "verde": np.array([2.55, 0.5, 0.0])} node_list = VGroup() for n, p in vert.items(): node_list.add(VGroup( Circle(radius=0.86, stroke_width=6, color=COL[n], fill_color="#121C33", fill_opacity=1).move_to(p), Text(n, font=FONT, font_size=27, weight=BOLD, color=COL[n]).move_to(p))) arrows = VGroup() for a, c in (("rojo", "celeste"), ("celeste", "verde"), ("verde", "rojo")): pa, pb = vert[a], vert[c] d = (pb - pa) / np.linalg.norm(pb - pa) f = CurvedArrow(pa + d * 1.02, pb - d * 1.02, angle=-0.55, color=COL[a], stroke_width=7, tip_length=0.26) arrows.add(f) b.play(LaggedStart(*[GrowFromCenter(n) for n in node_list], lag_ratio=0.2), run_time=0.8) b.play(LaggedStart(*[Create(f) for f in arrows], lag_ratio=0.3), run_time=max(0.9, b.floor - 1.6)) five = Text("5 de 9 siempre", font=FONT, font_size=44, weight=BOLD, color=AMBER) five.move_to(DOWN * 1.35) b.play(FadeIn(five, shift=UP * 0.2), run_time=0.45) with self.beat(10) as b: closing = VGroup( Text("El truco:", font=FONT, font_size=44, weight=BOLD, color=WHITE), Text("elegí SEGUNDO", font=FONT, font_size=66, weight=BOLD, color=AMBER), ).arrange(DOWN, buff=0.26).move_to(DOWN * 1.65) b.play(FadeOut(five), run_time=0.3) b.play(FadeIn(closing, shift=UP * 0.25), run_time=0.7) b.play(*[Indicate(f, color=WHITE, scale_factor=1.05) for f in arrows], run_time=0.9) self.finish()