48
{CurlyBraces2015: h3p://curlybraces.rocks}

Haxx with #### - Rob Clewley - Curly Braces 2015

Embed Size (px)

Citation preview

Page 1: Haxx with #### - Rob Clewley - Curly Braces 2015

{CurlyBraces2015:  h3p://curlybraces.rocks}  

Page 2: Haxx with #### - Rob Clewley - Curly Braces 2015

Take-aways

•  Learn  to  love  constraints  •  Don’t  give  up  before  analyzing  •  Performance  can  be  possible  in  high  level  languages  

• Hash  tables  are  underused  •  Example  in  a  game  

Page 3: Haxx with #### - Rob Clewley - Curly Braces 2015

• Sci-­‐fi  survival  adventure  • Roguelike-­‐ish  • Top-­‐down  2D  • Strategy  • Puzzles  

• EducaQonal  applicaQon  ?  •  Using  embedded  python  interpreter  in  

virtual  terminals  to  hack  ship’s  computers!  

Game application

Page 4: Haxx with #### - Rob Clewley - Curly Braces 2015
Page 5: Haxx with #### - Rob Clewley - Curly Braces 2015

•  Real  Qme  •  Detailed  ship  simulaQon  •  Open  world  •  Pure  Python  

Page 6: Haxx with #### - Rob Clewley - Curly Braces 2015

•  Real  Qme  •  Detailed  ship  simulaQon  •  Open  world  •  Pure  Python  

Page 7: Haxx with #### - Rob Clewley - Curly Braces 2015

Python  is  not  popularly  considered  to  be  a  high  performance  language  

…  but  I’m  good  at  it,  and  I  can  quickly  

build  large  systems  with  it  

Page 8: Haxx with #### - Rob Clewley - Curly Braces 2015

Python  is  not  popularly  considered  to  be  a  high  performance  language  

 …  but  that’s  not  always  true,  I’m  good  at  Python,  and  I  can  quickly  

build  large  systems  with  it  

Page 9: Haxx with #### - Rob Clewley - Curly Braces 2015

So  how  would  I  achieve  my  real  Qme  features?  

Page 10: Haxx with #### - Rob Clewley - Curly Braces 2015

So  how  would  I  achieve  my  real  Qme  features?  

 Let’s  consider  dynamic  updates  to  visibility  on  

map  

Page 11: Haxx with #### - Rob Clewley - Curly Braces 2015

•  Example:      Player  is  looking  East  in  a  small  room  

 …  then  strafes  Southwards  

Line of Sight / Field of View

Page 12: Haxx with #### - Rob Clewley - Curly Braces 2015

Line of Sight / Field of View

LOS:  Shadow  casQng  principle,      Bresenham  Line  Algorithm  

FOV  cone  

Page 13: Haxx with #### - Rob Clewley - Curly Braces 2015

Line of Sight / Field of View

LOS:  Shadow  casQng  principle,      Bresenham  Line  Algorithm  

FOV  cone  

Page 14: Haxx with #### - Rob Clewley - Curly Braces 2015

Line of Sight / Field of View

LOS:  Shadow  casQng  principle,      Bresenham  Line  Algorithm  

FOV  cone  

Page 15: Haxx with #### - Rob Clewley - Curly Braces 2015

Line of Sight / Field of View

LOS:  Shadow  casQng  principle,      Bresenham  Line  Algorithm  

FOV  cone  

Page 16: Haxx with #### - Rob Clewley - Curly Braces 2015

Line of Sight / Field of View

LOS:  Shadow  casQng  principle,      Bresenham  Line  Algorithm  

FOV  cone  

Page 17: Haxx with #### - Rob Clewley - Curly Braces 2015

Line of Sight / Field of View

LOS:  Shadow  casQng  principle,      Bresenham  Line  Algorithm  

FOV  cone  

Page 18: Haxx with #### - Rob Clewley - Curly Braces 2015

Line of Sight / Field of View

LOS:  Shadow  casQng  principle,      Bresenham  Line  Algorithm  

FOV  cone  

Page 19: Haxx with #### - Rob Clewley - Curly Braces 2015

Line of Sight / Field of View

LOS:  Shadow  casQng  principle,      Bresenham  Line  Algorithm  

FOV  cone  

Page 20: Haxx with #### - Rob Clewley - Curly Braces 2015

Line of Sight / Field of View

•  LOS  computaQon  between  all  pairs  of  enQQes  can  scale  like  n2  in  complexity  –  n  is  number  of  enQQes  (e.g.  Qles,  objects)  

•  Usually  performed  in  real  Qme  (every  clock  Qck)    –  brute  force  

•  Not  a  big  deal  with  GPUs  and  C++  

•  But  I’m  doing  this  single-­‐threaded  in  pure  python  –  besides,  there’s  more  to  compute  for  the  simulaQon  each  Qck  

Page 21: Haxx with #### - Rob Clewley - Curly Braces 2015

Line of Sight / Field of View

•  LOS  computaQon  between  all  pairs  of  enQQes  can  scale  like  n2  in  complexity  –  n  is  number  of  enQQes  (e.g.  Qles)  

•  Usually  performed  in  real  Qme  (every  clock  Qck)    –  brute  force  

•  Not  a  big  deal  with  GPUs  and  C++  

•  But  I’m  doing  this  single-­‐threaded  in  pure  Python  –  besides,  there’s  more  to  compute  for  the  simulaQon  each  Qck  

Page 22: Haxx with #### - Rob Clewley - Curly Braces 2015

Learn to love constraints

•  They  are  opportuniQes  for  creaQvity  and  novelty  –  Turn  them  into  a  feature,  e.g.  Silent  Hill’s  use  of  fog  

h3p://www.oddpulse.com/19-­‐awesome-­‐facts-­‐you-­‐probably-­‐didnt-­‐know-­‐about-­‐of-­‐famous-­‐video-­‐games/  

Page 23: Haxx with #### - Rob Clewley - Curly Braces 2015

Design simplifications

•  Large  square  Qles  for  all  floors  

•  N,  S,  E,  W  wall  combinaQons  only  

•  Discrete  Qle-­‐to-­‐Qle  player  moQon  only  

•  Cone  of  forward  vision  only  

•  Maximum  visual  range  imposed    

Page 24: Haxx with #### - Rob Clewley - Curly Braces 2015

Opportunities

•  Restricted  FOV  creates  tension  •  Simple  Qles  create  a  retro  game  feel  

•  Design  permits  pre-­‐computaQon  of  LOS  •  wurt?  

•  Replace  FLOPs  with  data  table  lookups!  – actually,  a  hash  table  

Page 25: Haxx with #### - Rob Clewley - Curly Braces 2015

Opportunities

•  Tension  •  Retro  feel  

•  Design  permits  pre-­‐computaQon  of  LOS  • wurt?  

•  Replace  FLOPs  with  data  table  lookups!  –  actually,  a  hash  table  

Page 26: Haxx with #### - Rob Clewley - Curly Braces 2015

Opportunities

•  Tension  •  Retro  feel  

•  Design  permits  pre-­‐computaQon  of  LOS  • wurt?  

•  Replace  FLOPs  with  data  table  lookups!  –  actually,  a  hash  table  

Page 27: Haxx with #### - Rob Clewley - Curly Braces 2015

Time vs. Memory

Page 28: Haxx with #### - Rob Clewley - Curly Braces 2015

Time vs. Memory

CPU  FLOPs  are  costly  

Page 29: Haxx with #### - Rob Clewley - Curly Braces 2015

RAM  use  is  cheap  

Time vs. Memory

CPU  FLOPs  are  costly  

Page 30: Haxx with #### - Rob Clewley - Curly Braces 2015

Opportunities

•  Tension  •  Retro  feel  

•  Design  permits  pre-­‐computaQon  of  LOS  • wurt?  

•  Replace  FLOPs  with  cheap  table  lookups!  –  actually,  from  a  hash  table  

Page 31: Haxx with #### - Rob Clewley - Curly Braces 2015

Divide and Conquer

•  Decompose  all  combinaQons  of      player  vs.  wall  

 •  Pre-­‐compute  the  LOS  combos    •  Store  them  for  lookup  at  runQme  

Page 32: Haxx with #### - Rob Clewley - Curly Braces 2015

Combinatorics

•  Four  possible  player  view  direcQons  •  N,  S,  E,  W  

 •  14  Qle  wall  possibiliQes  for  creaQng  shadow:  –  1  with  no  walls  (irrelevant)  –  4  with  single  walls  –  4  with  adjacent  double  walls  –  2  with  opposite  double  walls  –  4  triple  walls  –  1  four  walls  (irrelevant,  back  wall  not  visible)  

Page 33: Haxx with #### - Rob Clewley - Curly Braces 2015

Big buts (no lie)

•  Many  possible  room  outlines  on  a  map  

•  Many  possible  player  locaQons  on  a  map  

•  Even  a  small  50  x  50  map  has  2500  x  4  =  10k    possible  player  viewpoints  

•  …  and  walls  are  potenQally  breakable/buildable  •  So  don’t  pre-­‐compute  on  a  whole  map  basis  

Page 34: Haxx with #### - Rob Clewley - Curly Braces 2015

Scalable, modular, general For  the  East  facing  direcQon:    

 For  each  of  the  14  wall  combos  in  Qle:      For  each  Qle  relaQve  locaQon  within  max  range:        Compute  Qles  in  “shadow”  using  trigonometry,  etc.  [EXPENSIVE]          up  to  max  range  (e.g.  18  Qles)        Add  to  nested  hash  table:  

{  E:          {      E:          {  []  },  

 W:          {  []  },        N:    {  []  },          S:    {  []  },      EW:      {  []  },        NS:    {  []  },      <  etc.  >  

       }  }      

Page 35: Haxx with #### - Rob Clewley - Curly Braces 2015

Scalable, modular, general For  the  East  facing  direcQon:    

 For  each  of  the  14  wall  combos  in  Qle:    South+East      For  each  Qle  relaQve  locaQon  within  max  range:    (+3,  -­‐1)        Compute  Qles  in  “shadow”  using  trigonometry,  etc.  [EXPENSIVE]          up  to  max  range  (e.g.  18  Qles)        Add  to  nested  hash  table:  

{  E:          {    SE:  

   {  (3,-­‐1):    [  (4,-­‐1),  (5,-­‐1),  (3,-­‐2),  (4,-­‐2),          (5,-­‐2),  (4,-­‐3),  (5,-­‐3),  …  ]      }  

       }  }      

Page 36: Haxx with #### - Rob Clewley - Curly Braces 2015

Scalable, modular, general For  the  East  facing  direcQon:    

 For  each  of  the  14  wall  combos  in  Qle:    South+East      For  each  Qle  relaQve  locaQon  within  max  range:    (+3,  -­‐2)        Compute  Qles  in  “shadow”  using  trigonometry,  etc.  [EXPENSIVE]            up  to  max  range  (e.g.  18  Qles)        Add  to  nested  hash  table:  

{  E:          {    SE:  

   {  (3,-­‐1)  [    (4,-­‐1),  (5,-­‐1),  (3,-­‐2),  (4,-­‐2),          (5,-­‐2),  (4,-­‐3),  (5,-­‐3),  …],          (3,-­‐2):    [  (4,-­‐2),  (3,-­‐3),  (4,-­‐3),  (5,-­‐3),          (4,-­‐4),  (5,-­‐4),  …  ]      }  

       }  }    

Page 37: Haxx with #### - Rob Clewley - Curly Braces 2015

Solution with reusable parts

Several  wall  combos  can  REUSE  shadows  already  computed  at  this  posiQon  Rotate  East-­‐facing  hash  table  for  other  facing  direcQons  [FURTHER  REUSE!]  Serialize  whole  table  (~26k  lists)  to  file  for  reloading  at  game’s  start    {  E:          {    SE:  

   {  (3,-­‐1):    [  (4,-­‐1),  (5,-­‐1),  (3,-­‐2),  (4,-­‐2),          (5,-­‐2),  (4,-­‐3),  (5,-­‐3),  …  ],          (3,-­‐2):    [  (4,-­‐2),  (3,-­‐3),  (4,-­‐3),  (5,-­‐3),          (4,-­‐4),  (5,-­‐4),  …  ],        <  etc.  >      },  

       <  etc.  >          },  N:  {  <  etc.  >  },  W:    {  <  etc.  >  },  S:  {  <  etc.  >  },  }    

Page 38: Haxx with #### - Rob Clewley - Curly Braces 2015

Runtime usage        Hash  table  lookup  has  O(1)  1me  complexity.  

 Each  Cme  Cck,  player  faces  some  direcCon,  v:      Radiate  outwards  in  square  rings  from  player:  (pre-­‐computed  relaQve  posiQons)            For  each  absolute  Qle  locaQon  in  ring    ∩    iniQal  FOV  cone:  

 Find  any  walls  here  (O(1)  hash  table  query,  not  O(n)  list  search)    For  each  wall:            Lookup  its  facing  direcQon,  w            Calculate  its  relaQve  posiQon  to  the  viewer,  rel_pos  

                 New  invisible  rel  posiQons      =      shadow_dict  [v]  [w]  [rel_pos]            Compute  the  absolute  Qle  posiQon  for  each  of  these            Add  these  to  the  list  of  invisible  locaQons  if  not  found  previously  

     Visible  locaQons  =    invert  the  list  of  invisibles  

Page 39: Haxx with #### - Rob Clewley - Curly Braces 2015

Runtime usage

FOV  cone  determines  iniQal  feasible  set  of  visible  

Qles  

Player  sprite  

Page 40: Haxx with #### - Rob Clewley - Curly Braces 2015

Runtime usage

r  =  1  

These  concentric  rings  are    also  pre-­‐computed  

Page 41: Haxx with #### - Rob Clewley - Curly Braces 2015

Runtime usage

Find  any  walls  =  O(1)  hash  table  lookup  

Page 42: Haxx with #### - Rob Clewley - Curly Braces 2015

Runtime usage

shadow_dict  [E]  [S]  [(1,-­‐1)]  

Page 43: Haxx with #### - Rob Clewley - Curly Braces 2015

Runtime usage

shadow_dict  [E]  [S]  [(0,-­‐1)]  

Filtered  by  FOV  

Page 44: Haxx with #### - Rob Clewley - Curly Braces 2015

Runtime usage

shadow_dict  [E]  [S]  [(-­‐1,-­‐1)]  

Filtered  by  FOV  

Page 45: Haxx with #### - Rob Clewley - Curly Braces 2015

Runtime usage

r  =  2  

shadow_dict  [E]  [S]  [(2,-­‐1)]  

Eliminate  ring  Qles  that  are  

already  not  in  possibly  visible  Qle  set  

Page 46: Haxx with #### - Rob Clewley - Curly Braces 2015

Runtime usage

r  =  3  

SE  wall  combo!  shadow_dict  [E]  [SE]  [(3,-­‐1)]  

…  and  so  on  

Page 47: Haxx with #### - Rob Clewley - Curly Braces 2015

Take-home messages

           Don’t  underesQmate  high-­‐level  languages      if  you  work  with  constraints  wisely  

   DicConaries  are  unordered,  and  the  map  is  a  grid!        Don’t  use  a  data  structure  (2D  array)  just  because  it    

               mimics  the  “physical”  structure  it  represents  (grid)    

 VectorizaQon  (inc.  list  comprehension)  is  fast    

Page 48: Haxx with #### - Rob Clewley - Curly Braces 2015

Take-home messages

Tim  Peters*:          “Code  wri3en  with  Python  dicQonaries  is            a  gazillion  Qmes  faster  than  C.”    (i.e.  compared  to  using  non-­‐hash  table  data  types  in  C)    Raymond  Heunger:          “If  you  need  a  [dicQonary]  but  try  something  else,  it                        will  be  dog  slow  no  ma3er  what  language  you  use.”  

Sources:    *  Quoted  by  Raymond  Heunger,  at  least    h3ps://www.youtube.com/watch?v=hYUsssClE94    h3ps://wiki.python.org/moin/TimeComplexity      h3p://www.laurentluce.com/posts/python-­‐dicQonary-­‐implementaQon/      

(Hash  tables  are  called  “dicQonaries”  in  Python,  a.k.a.  “mappings”)