Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to port this NetHack function to Python?
    text
    copied!<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>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload