Tursom Log
恐龙与骨头 · 历史基线

恐龙原版捷径

保留优化前的独立版本,使用列表与占用字典维护蛇身。

使用说明

  1. 用于复核旧结果和算法对比。成本模型中的 old 读取这个文件;它也保留原策略的增长死路。

运行前提与限制

独立脚本需要 32×32 农场、恐龙科技和足够支付一局苹果的材料;每局开始与结束都会清场,运行前停止其他无人机。

当前轻量捷径保留了原策略的增长死路,不保证每局填满。起点 (0,0)、苹果依次为 (0,1) 和 (1,0) 就是已知反例;遇到死路后收尾并停止。

20 个随机种子的本地模型中,轻量版与旧版移动步数一致,算法主体预计 tick 减少约 92.3%。这是成本模型估算,尚未由游戏引擎实测确认;综合脚本中的恐龙实现仍是旧策略。

运行环境:游戏内代码窗口。说明由 AI 辅助整理;更多对照版本、测试和记录见恐龙与骨头目录。

完整源码

dinosaur_32_baseline.py · 136 行。代码块右上角可复制完整代码。

# The Farmer Was Replaced - standalone 32x32 dinosaur snake farm.
# Run this file in the game, with no other drones working on the farm.
# Each round clears the entire farm before and after playing.
# Requires Dinosaurs and enough apple materials to fund a full 32x32 round.
# Stops when a full round can no longer be funded.
WORLD_SIZE = 32
# Use target-aware shortcuts below this tail length, then follow the cycle.
DINO_SHORTCUT_LIMIT = 512


def dino_cycle_index(x, y):
	if y == 0:
		return x
	if x == 0:
		return WORLD_SIZE * WORLD_SIZE - y
	if y % 2 == 1:
		return WORLD_SIZE + (y - 1) * (WORLD_SIZE - 1) + WORLD_SIZE - 1 - x
	return WORLD_SIZE + (y - 1) * (WORLD_SIZE - 1) + x - 1


def choose_dino_move(target_x, target_y, body, occupied, grow):
	x = get_pos_x()
	y = get_pos_y()
	head_index = dino_cycle_index(x, y)
	target_index = dino_cycle_index(target_x, target_y)
	cycle_size = WORLD_SIZE * WORLD_SIZE
	food_distance = (target_index - head_index) % cycle_size

	directions = [East, North, West, South]
	next_x = [x + 1, x, x - 1, x]
	next_y = [y, y + 1, y, y - 1]
	best_direction = None
	best_advance = 0
	tail = -1
	if len(body) > 0:
		tail = body[0]
		tail_x = tail % WORLD_SIZE
		tail_y = tail // WORLD_SIZE
		tail_distance = (
			dino_cycle_index(tail_x, tail_y) - head_index
		) % cycle_size
		if grow:
			tail_distance -= 1
		if tail_distance < food_distance:
			food_distance = tail_distance

	for index in range(4):
		nx = next_x[index]
		ny = next_y[index]
		if nx >= 0 and nx < WORLD_SIZE and ny >= 0 and ny < WORLD_SIZE:
			node = nx + ny * WORLD_SIZE
			blocked = node in occupied
			# On a normal move the final tail segment moves out of the way.
			if blocked and not (not grow and node == tail):
				continue
			advance = (dino_cycle_index(nx, ny) - head_index) % cycle_size
			# Never overtake the next apple in Hamilton-cycle order.
			if advance > 0 and advance <= food_distance:
				if best_direction == None:
					best_advance = advance
					best_direction = directions[index]
				elif len(body) < DINO_SHORTCUT_LIMIT:
					if advance > best_advance:
						best_advance = advance
						best_direction = directions[index]
				elif advance < best_advance:
					best_advance = advance
					best_direction = directions[index]

	return best_direction


def move_dinosaur_to(target_x, target_y, body, occupied):
	# Leaving the current apple grows the tail on the first move only.
	grow = True
	while get_pos_x() != target_x or get_pos_y() != target_y:
		direction = choose_dino_move(target_x, target_y, body, occupied, grow)
		if direction == None:
			return False

		old_position = get_pos_x() + get_pos_y() * WORLD_SIZE
		if not move(direction):
			return False

		if grow:
			body.append(old_position)
			occupied[old_position] = True
			grow = False
		else:
			if len(body) > 0:
				tail = body.pop(0)
				occupied.pop(tail)
			body.append(old_position)
			occupied[old_position] = True

	return True


def dinosaur_once():
	if num_unlocked(Unlocks.Dinosaurs) == 0:
		return False
	cost = get_cost(Entities.Apple)
	if cost == None:
		return False
	for item in cost:
		if num_items(item) < cost[item] * WORLD_SIZE * WORLD_SIZE:
			return False

	clear()
	change_hat(Hats.Dinosaur_Hat)
	body = []
	occupied = {}
	next_apple = measure()

	while next_apple != None:
		if not move_dinosaur_to(next_apple[0], next_apple[1], body, occupied):
			break
		# Standing on the current apple reveals the following apple.
		next_apple = measure()

	change_hat(Hats.Straw_Hat)
	clear()
	return True



def main():
	if get_world_size() != WORLD_SIZE:
		quick_print("Dinosaur script requires a 32x32 farm.")
		return
	while dinosaur_once():
		pass
	quick_print("Dinosaur farming stopped: check Dinosaurs unlock and apple materials.")


main()