+---
+
+- image: images/YDKDJ title.png
+- title:
+ head: Part 1
+ text: |
+ Just Your Friendly Neigborhood Dinosaurs
+- q: >
+ In the webcomic Dinosaur Comics, T-Rex rambles about his many existential
+ crises with his gay best friend, who provides a sane counterpoint. What
+ kind of dinosaur is T-Rex's buddy?
+ a:
+ - Dromiceiomimus
+ - Utahraptor
+ - Pterodactyl
+ - Allosaurus
+ w: 1
+- q: >
+ The Dinobots were a group of five Autobot Transformers who
+ (surprise) transformed into dinosaurs. They included Grimlock, a T.
+ Rex; Slag, a Triceratops; Sludge, an Apatosaurus; Snarl, a
+ Stegosaurus; and Swoop, a what?
+ a:
+ - Elasmosaurus
+ - Ankylosaurus
+ - Pteranodon
+ - Struthiomimus
+ w: 2
+- title:
+ head: Video Question!
+ text: ''
+- video: videos/Dino.mp4
+- q: >
+ What kind of dinosaur is Dino?
+ a:
+ - Apatosaurus
+ - Brontosaurus
+ - Parasaurolophus
+ - Snorkasaurus
+ w: 3
+- q: >
+ In the 1988 movie The Land Before Time, Littlefoot and his four
+ friends confront disaster and loss. They ultimately survive the
+ famine by journeying to the Great Valley, where they reunite with
+ their families and find plentiful amounts of what type of food?
+ a:
+ - Tree-Stars
+ - Marionberries
+ - Fern-Gullies
+ - Frond-Petals
+ w: 0
+- title:
+ head: Video Question!
+ text: ''
+- video: videos/Walk the Dinosaur.mp4
+- q: What is the name of that band?
+ a:
+ - Was (Not Was)
+ - Dinotasia
+ - Wham!
+ - Men Without Hats
+ w: 0
+ points: 20
+
+
+- title:
+ head: Part 2
+ text: |
+ Being a dinosaur nerd in grade
+ school sure is paying off now!
+- q: >
+ Because of limited and often fragmentary specimens, the study of
+ dinosarus has been fraught with mistakes. Apatosaurus, for example,
+ was so incomplete when it was discovered that it was called by a
+ completely different name. What was that name?
+ a:
+ - Diplodocus
+ - Camarasaurus
+ - Brachiosaurus
+ - Brontosaurus
+ w: 3
+ points: 15
+- q: >
+ Tyrannosaurus Rex is known as the most fearsome carnivore of the late
+ Cretaceous period (despite being featured prominently in Jurassic
+ Park). "Rex" is Latin for "King", but what does "Tyrannosaurus"
+ mean?
+ a:
+ - Terrible Lizard
+ - Tyrian Lizard
+ - Tyrant Lizard
+ - Totally Awesome Lizard
+ w: 2
+ points: 15
+- q: >
+ For most of paleontological understanding, dinosaurs have been
+ covered in scales much like their modern reptilian relatives. But
+ recently, it is theorized that some dinosaurs, including
+ Tyrannosaurs and Velociraptors, were covered in what?
+ a:
+ - hair
+ - quills
+ - Duck Tape
+ - feathers
+ w: 3
+ points: 15
+- q: >
+ Dinosaurs are roughly divided into two groups based on their hip
+ structure. Saurischians have a "lizard-hipped" configuration, while
+ Ornithischians have hipbones similar to what?
+ a:
+ - frogs
+ - birds
+ - cats
+ - mushrooms
+ w: 1
+ points: 15
+- q: >
+ With a name meaning "terrible lizard," it's not that weird to be
+ afraid of dinosaurs. What is the psychological term for fear of
+ dinosaurs?
+ a:
+ - Dinophobia
+ - Tyrannophobia
+ - Ornithoscelidaphobia
+ - Icthyophobia
+ w: 2
+ points: 30
+
+- video: videos/Jurassic Park.mp4
+- title:
+ head: Part 3
+ text: |
+ Bring Back Dinosaurs?
+ What Could Possibly Go Wrong?
+- q: >
+ In Jurassic Park, Dennis Nedry tried to make off with a cache of dinosaur
+ embryos hidden in a can of Barbasol shaving foam. Unfortunately for him,
+ he didn't quite make it. What dinosaur did he get killed and eaten by?
+ a:
+ - Velociraptor
+ - Dilophosaurus
+ - Tyrannosaurus
+ - Ankylosaurus
+ w: 1
+ points: 20
+- q: >
+ Billionaire John Hammond whisks away paleontologists Alan Grant and
+ Ellie Sattler to Isla Nublar, where he reveals that his company has
+ developed the technology to clone dinosaurs from fossil tissue.
+ What is the name of John Hammond's company?
+ a:
+ - Massive Dynamics
+ - Initech
+ - InGen
+ - Veridian Dynamics
+ w: 2
+ points: 20
+- title:
+ head: Video Question!
+ text: ''
+- video: videos/Jurassic Cats.mp4
+- q: What dinosaur was expertly replaced by cats in that video?
+ a:
+ - Allosaurus
+ - Velociraptor
+ - Utahraptor
+ - Compsognathus
+ w: 1
+ points: 20
+- q: >
+ In addition to the various physical safeguards that failed, several
+ biological safeguards were put in place to keep the park dinosaurs
+ under control. The first and most basic was that all the dinosaurs
+ were female. Later, it was discovered that some dinosaurs could
+ self-sex change and were breeding because of donor DNA from which
+ animal?
+ a:
+ - frogs
+ - lizards
+ - salamanders
+ - chickens
+ w: 0
+ points: 20
+- q: >
+ The first was that all the dinosaurs were female. The
+ second was that they were engineered to have an inability to produce
+ which amino acid?
+ a:
+ - Leucine
+ - Phenylalanine
+ - Methionine
+ - Lysine
+ w: 3
+ points: 40
+#!/usr/bin/python
+import curses
+import yaml
+import time
+import os, sys
+
+f = open('dino-jack.yml')
+script = yaml.load(f)
+f.close()
+
+class Player:
+ def __init__(self, name):
+ self.name = name
+ self.score = 0
+
+def display_video(file):
+ os.system('omxplayer -b "%s" >/dev/null 2>&1' % file)
+
+def display_image(file):
+ os.spawnlp(os.P_WAIT, 'fbv', 'fbv', file)
+
+players = []
+player_stride = 0
+script_index = 0
+question_n = 1
+
+window = curses.initscr()
+curses.start_color()
+h, w = window.getmaxyx()
+
+# Initialize colors
+curses.init_pair(1, curses.COLOR_YELLOW, curses.COLOR_BLACK)
+curses.init_pair(2, curses.COLOR_CYAN, curses.COLOR_BLACK)
+curses.init_pair(3, curses.COLOR_BLUE, curses.COLOR_BLACK)
+curses.init_pair(4, curses.COLOR_GREEN, curses.COLOR_BLACK)
+
+# Question window
+qwin = window.derwin(12, w - 10, 5, 5)
+qwin.attrset(curses.color_pair(1) | curses.A_BOLD)
+qwin_h, qwin_w = qwin.getmaxyx()
+
+# Answers window
+awin = window.derwin(8, w - 10, h - 13, 5)
+awin.attrset(curses.color_pair(2))
+awin_h, awin_w = awin.getmaxyx()
+
+# Players window
+pwin = window.derwin(3, w - 6, h - 4, 2)
+pwin.attrset(curses.color_pair(3))
+pwin_h, pwin_w = pwin.getmaxyx()
+
+def wrap(text, w):
+ r = []
+ for line in text.split('\n'):
+ i = 0
+ l = len(line)
+ if l == 0:
+ r.append(line)
+ continue
+ while i < l:
+ j = i + w
+ if j >= l:
+ r.append(line[i:])
+ break
+ else:
+ while line[j] != ' ':
+ j -= 1
+ r.append(line[i:j])
+ i = j + 1
+ return r
+
+def display_question_q(item):
+ qy = 0
+ for line in wrap(item['q'], qwin_w):
+ qx = 0
+ for c in line:
+ qwin.addstr(qy, qx, line[qx])
+ qwin.refresh()
+ qx += 1
+ time.sleep(0.04)
+ qy += 1
+
+aletters = ['A', 'B', 'C', 'D']
+def display_answers(item):
+ ay = 0
+ for answer in item['a']:
+ awin.addstr(ay, 0, "%s)" % aletters[ay])
+ awin.refresh()
+ time.sleep(0.5)
+ awin.addstr(ay, 3, answer)
+ awin.refresh()
+ time.sleep(1.0)
+ ay += 1
+ window.getch(h - 1, w - 1)
+ ay = item['w']
+ awin.chgat(ay, 0, 3 + len(item['a'][ay]), curses.A_REVERSE)
+ awin.refresh()
+
+ while True:
+ to = window.getch(h - 1, w - 1)
+ if chr(to) == 'x':
+ break
+ try:
+ player = int(chr(to), 16) - 1
+ except ValueError:
+ continue
+ points = 10
+ if 'points' in item:
+ points = int(item['points'])
+ try:
+ players[player].score += points
+ except IndexError:
+ continue
+ break
+
+def display_question(item, n=0):
+ try:
+ points = item['points']
+ except KeyError:
+ points = 10
+ window.addstr(0, 0, "Question %d" % n, curses.color_pair(4))
+ window.addstr(0, w - 10, "%3d points" % points, curses.color_pair(4))
+ window.refresh()
+ display_players()
+ time.sleep(3)
+ display_question_q(item)
+ time.sleep(2)
+ display_answers(item)
+ display_players()
+ window.getch()
+ qwin.clear()
+ qwin.refresh()
+ awin.clear()
+ awin.refresh()
+
+def display_title(item):
+ window.clear()
+ head = item['title']['head']
+ lines = item['title']['text'].split('\n')
+ def put_line(y, str, attr=0):
+ x = w / 2 - len(str) / 2
+ window.addstr(y, x, str, attr)
+ window.refresh()
+ l = len(lines) + 2
+ y = h / 2 - l / 2
+ put_line(y, head, curses.A_BOLD)
+ time.sleep(1)
+ y += 2
+ for l in lines:
+ put_line(y, l)
+ time.sleep(0.5)
+ y += 1
+ window.getch()
+ window.clear()
+ window.refresh()
+
+def display_players():
+ pwin.clear()
+ px = 0
+ py = 0
+ c = 1
+ for p in players:
+ pwin.addstr(py, px, "%1X " % c)
+ pwin.addstr("%-*s " % (player_stride, p.name), curses.A_BOLD)
+ pwin.addstr("%3d" % p.score, curses.A_REVERSE)
+ px += player_stride + 8
+ if px >= pwin_w - 2:
+ px = 0
+ py += 1
+ c += 1
+ pwin.refresh()
+
+def gather_players():
+ global player_stride, players
+
+ ok = False
+
+ while not ok:
+ window.clear()
+ window.refresh()
+ window.addstr(4, 5, "Add up to 15 players. Enter a blank line")
+ window.addstr(5, 5, "to finish.")
+ n = 1
+ players = []
+ name = "X"
+ while name != '' and len(players) < 15:
+ window.addstr(6 + n, 5, "Player %s's name: " % n)
+ name = window.getstr()
+ if len(name) > player_stride:
+ player_stride = len(name)
+ players.append(Player(name))
+ n += 1
+ if name == '':
+ players.pop()
+ display_players()
+ window.addstr(7 + n, 5, "%s players. Is this correct? " % len(players))
+ answer = window.getstr()
+ if answer.lower() == 'y':
+ ok = True
+
+def save_state():
+ state = dict(
+ players = players,
+ index = script_index,
+ question = question_n
+ )
+ f = open('state.yml', 'w')
+ yaml.dump(state, f)
+ f.close()
+
+def load_state(filename):
+ global players, script_index, question_n
+ f = open(filename)
+ state = yaml.load(f)
+ f.close()
+ players = state['players']
+ script_index = state['index']
+ question_n = state['question']
+
+def main():
+ global script_index, question_n
+ if len(sys.argv) > 1:
+ load_state(sys.argv[1])
+ else:
+ gather_players()
+
+ window.clear()
+ window.refresh()
+ curses.noecho()
+ display_players()
+ while script_index < len(script):
+ save_state()
+ item = script[script_index]
+ if 'image' in item:
+ display_image(item['image'])
+ elif 'video' in item:
+ display_video(item['video'])
+ elif 'title' in item:
+ display_title(item)
+ elif 'q' in item:
+ display_question(item, question_n)
+ question_n += 1
+ script_index += 1
+ save_state()
+ window.addstr(h / 2, w / 2 - 8, "G A M E O V E R")
+ window.getch()
+ curses.endwin()
+
+try:
+ main()
+except KeyboardInterrupt:
+ pass
+
+curses.endwin()