我试图编写一个Python函数,它返回与NetHack游戏中相同的月相值。这可以在hacklib.c中找到。在
我试图简单地从NetHack代码中复制相应的函数,但我不相信我得到了正确的结果。在
我写的函数是phase_of_the_moon()
。在
我在网上找到的函数position()
和{
我希望我的函数和“控制”函数至少能给出相同的月相,但目前它们没有,我也不知道为什么!在
以下是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 );
}
下面是getlt()
函数(也在hacklib.c中):
下面是我的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()
编写的代码在很大程度上是不稳定的,您需要使其具有可测试性。所以,你需要C代码是:
现在您可以使用多个时间值运行测试。另一种方法是伪造
getlt()
。在然后需要在Python代码中进行并行更改。然后创建一个包含
time_t
值的文件,该文件可以被Python和C读取,然后转换成适当的结构(通过C中的localtime()
)。然后你就能看到事情的偏差。在编辑:我发现的两个“问题”都是基于对
tm
结构的误解。为了评论中的讨论,我将保留完整的答案,但请将您的投票留给可能真正正确的人。;—)注意:我对C时结构不太熟悉;我主要是不熟悉为
strftime
提供的字段文档。在我在你的港口看到两个“虫子”。首先,我认为}。其次,您对
tm_year
应该是没有世纪的年份,而不是减去1900年的年份,因此,goldn
应该是{diy
的计算是从零开始的,而tm_yday
看起来(同样是在文档中)是基于1的。但是,我对后者并不确定,因为仅仅修复goldn
行就可以得到正确的结果(至少在今天是这样),而同时修复这两条线都会给出错误的答案:同样,这主要是猜测。请客气点。:-)
我已经迟到很久了,但是alt.org公司服务器通过网络显示的pom每天只在cron上更新几次,所以如果你离它稍微远一点,这可能是原因。游戏本身从nethack代码本身运行,因此不会遭受同样的缓存问题。-德鲁(alt.org公司业主)
相关问题 更多 >
编程相关推荐