title: How to port this NetHack function to Python?
body: <p>I am trying to write a Python function which returns the same moon phase value as in the game NetHack. This is found in <a href="http://nethack.wikia.com/wiki/Source:Hacklib.c#phase_of_the_moon" rel="nofollow noreferrer">hacklib.c</a>.</p>
  
  <p>I have tried to simply copy the corresponding function from the NetHack code but I don't believe I am getting the correct results.</p>
  
  <p>The function which I have written is <code>phase_of_the_moon()</code>.</p>
  
  <p>The functions <code>position()</code> and <code>phase()</code>, I found on the net, and I am using them as an indication of the success of my function. They are very accurate and give results which approximately match the nethack.alt.org server (see <a href="http://alt.org/nethack/moon/pom.txt" rel="nofollow noreferrer">http://alt.org/nethack/moon/pom.txt</a>). What I am after however is an exact replication of the original NetHack function, idiosyncrasies intact.</p>
  
  <p>I would expect my function and the 'control' function to give the same moon phase at least, but currently they do not and I'm not sure why!</p>
  
  <p>Here is the NetHack code:</p>
  
  <pre><code>/*
   * moon period = 29.53058 days ~= 30, year = 365.2422 days
   * days moon phase advances on first day of year compared to preceding year
   *  = 365.2422 - 12*29.53058 ~= 11
   * years in Metonic cycle (time until same phases fall on the same days of
   *  the month) = 18.6 ~= 19
   * moon phase on first day of year (epact) ~= (11*(year%19) + 29) % 30
   *  (29 as initial condition)
   * current phase in days = first day phase + days elapsed in year
   * 6 moons ~= 177 days
   * 177 ~= 8 reported phases * 22
   * + 11/22 for rounding
   */
  int
  phase_of_the_moon()     /* 0-7, with 0: new, 4: full */
  {
      register struct tm *lt = getlt();
      register int epact, diy, goldn;
  
      diy = lt-&gt;tm_yday;
      goldn = (lt-&gt;tm_year % 19) + 1;
      epact = (11 * goldn + 18) % 30;
      if ((epact == 25 &amp;&amp; goldn &gt; 11) || epact == 24)
          epact++;
  
      return( (((((diy + epact) * 6) + 11) % 177) / 22) &amp; 7 );
  }
  </code></pre>
  
  <p>Here is the <code>getlt()</code> function (also in hacklib.c):</p>
  
  <pre><code>static struct tm *
  getlt()
  {
      time_t date;
  
  #if defined(BSD) &amp;&amp; !defined(POSIX_TYPES)
      (void) time((long *)(&amp;date));
  #else
      (void) time(&amp;date);
  #endif
  #if (defined(ULTRIX) &amp;&amp; !(defined(ULTRIX_PROTO) || defined(NHSTDC))) || (defined(BSD) &amp;&amp; !defined(POSIX_TYPES))
      return(localtime((long *)(&amp;date)));
  #else
      return(localtime(&amp;date));
  #endif
  }
  </code></pre>
  
  <p>Here is my Python code:</p>
  
  <pre><code>from datetime import date
  
  def phase_of_the_moon():
     lt = date.today()
  
     diy = (lt - date(lt.year, 1, 1)).days
     goldn = ((lt.year - 1900) % 19) + 1
     epact = (11 * goldn + 18) % 30;
     if ((epact == 25 and goldn &gt; 11) or epact == 24):
        epact += 1
     return ( (((((diy + epact) * 6) + 11) % 177) / 22) &amp; 7 )
  
  import math, decimal, datetime
  dec = decimal.Decimal
  
  def position(now=None): 
     if now is None: 
        now = datetime.datetime.now()
  
     diff = now - datetime.datetime(2001, 1, 1)
     days = dec(diff.days) + (dec(diff.seconds) / dec(86400))
     lunations = dec("0.20439731") + (days * dec("0.03386319269"))
  
     return lunations % dec(1)
  
  def phase(pos): 
     index = (pos * dec(8)) + dec("0.5")
     index = math.floor(index)
     return {
        0: "New Moon", 
        1: "Waxing Crescent", 
        2: "First Quarter", 
        3: "Waxing Gibbous", 
        4: "Full Moon", 
        5: "Waning Gibbous", 
        6: "Last Quarter", 
        7: "Waning Crescent"
     }[int(index) &amp; 7]
  
  def phase2(pos): 
     return {
        0: "New Moon", 
        1: "Waxing Crescent", 
        2: "First Quarter", 
        3: "Waxing Gibbous", 
        4: "Full Moon", 
        5: "Waning Gibbous", 
        6: "Last Quarter", 
        7: "Waning Crescent"
     }[int(pos)]
  
  def main():
     ## Correct output
     pos = position()
     phasename = phase(pos)
     roundedpos = round(float(pos), 3)
     print "%s (%s)" % (phasename, roundedpos)
  
     ## My output
     print "%s (%s)" % (phase2(phase_of_the_moon()), phase_of_the_moon())
  
  if __name__=="__main__": 
     main()
  </code></pre>