Estoy tratando de escribir una función de Python que devuelva el mismo valor de fase lunar que en el juego NetHack. Esto se encuentra en hacklib.c.¿Cómo portar esta función de NetHack a Python?
He intentado simplemente copiar la función correspondiente del código de NetHack, pero no creo que esté obteniendo los resultados correctos.
La función que he escrito es phase_of_the_moon()
.
Las funciones position()
y phase()
, las encontré en la red, y las estoy usando como una indicación del éxito de mi función. Son muy precisos y dan resultados que coinciden aproximadamente con el servidor nethack.alt.org (ver http://alt.org/nethack/moon/pom.txt). Sin embargo, lo que busco es una replicación exacta de la función original de NetHack, la idiosincrasia intacta.
Espero que mi función y la función de "control" den la misma fase lunar al menos, pero actualmente no lo hacen y no estoy seguro de por qué.
Este es el código NetHack:
/*
* 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->tm_yday;
goldn = (lt->tm_year % 19) + 1;
epact = (11 * goldn + 18) % 30;
if ((epact == 25 && goldn > 11) || epact == 24)
epact++;
return((((((diy + epact) * 6) + 11) % 177)/22) & 7);
}
Aquí es la función getlt()
(también en hacklib.c):
static struct tm *
getlt()
{
time_t date;
#if defined(BSD) && !defined(POSIX_TYPES)
(void) time((long *)(&date));
#else
(void) time(&date);
#endif
#if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) || (defined(BSD) && !defined(POSIX_TYPES))
return(localtime((long *)(&date)));
#else
return(localtime(&date));
#endif
}
Aquí está mi código Python:
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 > 11) or epact == 24):
epact += 1
return ((((((diy + epact) * 6) + 11) % 177)/22) & 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) & 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()
Ah, el código de nethack ... ahora es un código complejo. – Craig
Lo sé, pero seguro que puedo lidiar con una función teensy weety leetle !! – nakedfanatic
Por un lado, la línea que define 'epact' termina con un punto y coma. – Zifre