農家は Replace() されました 攻略してみる
拡張しても移動・収穫・植え付けをしている間に育ち切ってしまうため、ドローンが増えるまでは、ある程度までしか拡張するメリットはない。畑サイズの変更のアンロックがかなり先なので、無駄に拡張しまくるとデバッグが大変になる。
Pythonライクらしい。スネークケースが一番の敵。
草
すぐ生えてくるので畑を拡張すればcan_harvest()の判定は必要ない。マップ端でループするので一方向に進めばよい。
while True:
move(North)
harvest()木
木は隣接すると成長速度が遅くなるため、格子状に植える。畑を拡張すればcan_harvest()の判定は必要ない。
while True:
for i in range(get_world_size()):
for j in range(get_world_size()):
harvest()
if ((i+j)%2)==0:
plant(Entities.Tree)
move(North)
move(East)ニンジン
上記から西の3列だけニンジンにしたバージョン。農場が広ければ水やりは必要ない。
for _ in range(get_pos_y()):
move(South)
for _ in range(get_pos_x()):
move(West)
while True:
for i in range(get_world_size()):
for j in range(get_world_size()):
harvest()
if i<3:
if get_ground_type() != Grounds.Soil:
till()
plant(Entities.Carrot)
if (get_water()<0.5):
use_item(Items.Water)
elif ((i+j)%2)==0:
plant(Entities.Tree)
move(North)
move(East)ヒマワリ
パワー(?)を収穫出来て一定時間超スピードになる最重要作物。花びら枚数の最適化の必要性を感じていないため今のところ保留。ランダムで肥料を追加し、Weird substance(奇妙な物質?)を回収する。
for _ in range(get_pos_y()):
move(South)
for _ in range(get_pos_x()):
move(West)
while True:
for i in range(get_world_size()):
for j in range(get_world_size()):
harvest()
if i<6:
if get_ground_type() != Grounds.Soil:
till()
plant(Entities.Carrot)
if (get_water()<0.5):
use_item(Items.Water)
if random()<0.1:
use_item(Items.Fertilizer)
elif i<9:
if get_ground_type() != Grounds.Soil:
till()
plant(Entities.Sunflower)
elif ((i+j)%2)==0:
plant(Entities.Tree)
move(North)
move(East)農場全体を埋め尽くすパンプキン
最初に(0,0)地点に行き、1行をループし続け全て収穫可能になったら次の行へ、を繰り返し最後の行がすべて収穫可能になったら収穫する作戦。効率は多分よくない。
change_hat(Hats.Brown_Hat)
plant_in_pass_x = False
world_size = get_world_size()
def plant_pumpkin():
global plant_in_pass_x
if get_ground_type() != Grounds.Soil:
till()
if not can_harvest():
plant(Entities.Pumpkin)
plant_in_pass_x = True
def plant_pumpkins():
global plant_in_pass_x
posX=get_pos_x()
posY=get_pos_y()
# --- パスの開始: ドローンを左下の角(0,0)に移動 ---
for _ in range(posY):
move(South)
for _ in range(posX):
move(West)
#1行をループし続け、全て収穫可能になったら1つ北へ
while True:
plant_in_pass = False
while True:
posX=get_pos_x()
posY=get_pos_y()
if posX==0 :
plant_in_pass_x = False
plant_pumpkin()
if (get_water()<0.2):
use_item(Items.Water)
move(East)
if not plant_in_pass_x and posX==world_size-1:
if posY!=world_size-1:
move(North)
break
if posY==world_size-1:
break
while True:
plant_pumpkins()
harvest()シンプル版パンプキン。収穫可能なパンプキン数を1個ずつカウントして植え直しがあったらリセット、ワールドサイズを超えたら収穫。6×6以上は効率が上がらないのでset_world_size(6)でいいかもしれない
change_hat(Hats.Straw_Hat)
count = 0
world_size = get_world_size()
def plant_pumpkin():
global count
#パンプキンを1個ずつカウントしていく。植え直しがあったらリセット
if get_ground_type() != Grounds.Soil:
till()
if not can_harvest():
plant(Entities.Pumpkin)
count = 0
else:
count += 1
def plant_pumpkins():
global count
count=0
while True:
plant_pumpkin()
move(North)
if get_pos_y()==0:
move(East)
#収穫可能なパンプキン数がワールドサイズを超えたら終わり
if count>world_size*world_size:
break
while True:
plant_pumpkins()
harvest()サボテンソート
畑の範囲外や植えてない畑との比較・スワップで問題が起きやすいので注意。measure()で数字が返ってくることを期待しているとNoneが返ってくる。
change_hat(Hats.Brown_Hat)
swaps_in_pass_y = False
swaps_in_pass_x = False
world_size = get_world_size()-1
def plant_cuctus():
global swaps_in_pass_x
global swaps_in_pass_y
if get_entity_type() != Entities.Cactus:
swaps_in_pass_x = True
swaps_in_pass_y = True
if get_ground_type() != Grounds.Soil:
till()
plant(Entities.Cactus)
def swap_cacti(times):
swap_cacti_dir(measure(),East,get_pos_x())
swap_cacti_dir(measure(),North,get_pos_y())
def swap_cacti_dir(curr_size,dir,pos):
#x方向の入れ替えは西に、y軸方向の入れ替えは南に戻る
global swaps_in_pass_y
global swaps_in_pass_x
if curr_size==None:
curr_size=0
# 現在のサボテンが北/東のサボテンより大きい場合スワップ。
next_size = measure(dir)
if next_size!=None and pos < world_size:
if curr_size> next_size:
swap(dir)
if dir==North:
swaps_in_pass_y = True
else:
swaps_in_pass_x = True
def sort_cacti():
global swaps_in_pass_y
global swaps_in_pass_x
# 畑がソートされるまでループ
while True:
# --- パスの開始: ドローンを左下の角(0,0)に移動 ---
for _ in range(get_pos_y()):
move(South)
for _ in range(get_pos_x()):
move(West)
# --- グリッド全体をスキャン ---
# 左から右へ、終わったら上の行へと移動。
max_y=0
#y軸走査
while True:
#x軸走査
while True:
swaps_in_pass_y=False
x=0
while True:
swaps_in_pass_x=False
plant_cuctus()
swap_cacti(x)
# 行の終わりに到達したら、次の行の開始位置に移動
if get_pos_x() >= world_size and not swaps_in_pass_x:
move(East)
break
# 行の次の位置に移動
if not swaps_in_pass_x:
if get_pos_x() <= world_size:
move(East)
#スワップがあった場合は1つ左に戻る
else :
if get_pos_x() > 0:
move(West)
# 植えるか南北のスワップがあった場合1つ南の行に戻る。
if get_pos_y()>0 and swaps_in_pass_y:
max_y=max(max_y,get_pos_y())
move(South)
else:
break
# 最北端に到達したら処理終了
if get_pos_y() >= world_size :
break
else:
# 南に戻ってスワップし終えた場合は元の処理位置まで戻る
max_y=max(max_y,get_pos_y())
if max_y==world_size:
max_y-=1
for _ in range(max_y-get_pos_y()+1):
move(North)
# 1回のパスでスワップが一度も行われなかった場合ソートは完了
if not swaps_in_pass_y and not swaps_in_pass_x:
break
while True:
sort_cacti()
harvest()ゲームの仕様上の問題は概ね回避できていると思います。力業での実装ですがパフォーマンスはよさげ。ノームソートというらしい。
curr_size> next_size:の判定を逆にするとSteamの実績の順序間違い(サボテンを逆向きにソート)もクリア可能。
シェーカーソートの方が効率が良さそう。
change_hat(Hats.Green_Hat)
#set_world_size(6)
WORLD_SIZE = get_world_size()
#---行ソート---
def sort_row_shaker(y):
left = 0
right = get_world_size() - 1
while left < right:
swapped = False
last_swap = left
move_to(left, y)
for x in range(left, right):
plant_if_needed()
curr = measure()
move(East)
plant_if_needed()
next_ = measure()
if curr != None and next_ != None and curr > next_:
swap(West)
swapped = True
last_swap = x + 1
right = last_swap
if not swapped:
break
swapped = False
last_swap = right
move_to(right, y)
for x in range(right, left, -1):
plant_if_needed()
curr = measure()
move(West)
plant_if_needed()
next_ = measure()
if curr != None and next_ != None and curr < next_:
swap(East)
swapped = True
last_swap = x - 1
left = last_swap
if not swapped:
break
#---列ソート---
def sort_column_shaker(x):
top = 0
bottom = get_world_size() - 1
while top < bottom:
swapped = False
last_swap = top
move_to(x, top)
for y in range(top, bottom):
plant_if_needed()
curr = measure()
move(North)
plant_if_needed()
next_ = measure()
if curr != None and next_ != None and curr > next_:
swap(South)
swapped = True
last_swap = y + 1
bottom = last_swap
if not swapped:
break
swapped = False
last_swap = bottom
move_to(x, bottom)
for y in range(bottom, top, -1):
plant_if_needed()
curr = measure()
move(South)
plant_if_needed()
next_ = measure()
if curr != None and next_ != None and curr < next_:
swap(North)
swapped = True
last_swap = y - 1
top = last_swap
if not swapped:
break
def shaker_sort_horizontal():
for y in range(get_world_size()):
sort_row_shaker(y)
def shaker_sort_vertical():
for x in range(get_world_size()):
sort_column_shaker(x)
def sort_cacti_grid():
shaker_sort_horizontal()
shaker_sort_vertical()
# --- Utils ---
def move_to(target_x, target_y):
while get_pos_x() > target_x:
move(West)
while get_pos_x() < target_x:
move(East)
while get_pos_y() > target_y:
move(South)
while get_pos_y() < target_y:
move(North)
def plant_if_needed():
if get_entity_type() != Entities.Cactus:
if get_ground_type() != Grounds.Soil:
till()
plant(Entities.Cactus)
return True
return False
# --- 実行ループ ---
while True:
sort_cacti_grid()
harvest()農場全体を埋め尽くす恐竜ハット
一筆書きで農場全体を周回し続ける作戦です。恐竜ハット装備中は尻尾が付くのでマップ端で反対側にワープできません。
少し改良を加えてショートカットするようにしました。
#clear()
#set_world_size(12)
change_hat(Hats.Dinosaur_Hat)
def MovDino(Dir):
global Apples
if move(Dir) :
return
else:
change_hat(Hats.Dinosaur_Hat)
Apples=0
next_x, next_y = (-1,-1)
Apples=0
worldSize=get_world_size()-1
shortcut_end=get_world_size()**1.72
while True:
pos_x=get_pos_x()
pos_y=get_pos_y()
if get_entity_type()==Entities.Apple and Apples < shortcut_end:
next_x, next_y = measure()
Apples += 1
#リンゴがワールドサイズ2乗の約半分を超えるとショートカットしない方が効率がいい
if Apples>=shortcut_end:
next_x, next_y = (-1,-1)
#一番南の列は西に横断
if pos_y==0 and can_move(West):
MovDino(West)
#偶数列は北に 北の端まで行ったら東に
elif pos_x%2==0:
if can_move(North) :
MovDino(North)
else:
MovDino(East)
#奇数列は南に
else:
#南端の一つ上まで来たら東に リンゴが西にある場合は南→西のルートへ
if pos_y==1 and pos_x!=worldSize:
if next_x!=-1 and pos_x>=next_x and can_move(South):
MovDino(South)
else:
MovDino(East)
#東にリンゴがある場合は東へ(東に行った後、偶数列では尻尾ぶつかり回避のため北に行く)
elif can_move(East) and next_x!=-1 and (next_y!=-1 and pos_x<next_x and pos_y==next_y or pos_x<next_x-1 or (pos_x<next_x and next_y==0)):
MovDino(East)
else:
MovDino(South)
#if num_items(Items.Bone) >= 33488928:
# break
動きを見るのが早いと思います。
迷路探索(右手法)
while True:
plant(Entities.Bush)
substance = get_world_size() * 2**(num_unlocked(Unlocks.Mazes) - 1)
use_item(Items.Weird_Substance, substance)
directions = [North, East, South, West]
#最初は北向き
index = 0
while get_entity_type() != Entities.Treasure:
#まず右を向く
index = (index + 1) % 4
#前が壁なら左周りで進める方向を探す
while not can_move(directions[index]):
index = (index - 1) % 4
move(directions[index])
harvest()恐らく公式のドキュメントのヒントで紹介されている方法
アルゴロジックという教育ゲームで似たようなことをやった記憶があります。
迷路の再利用(use_item(Items.Weird_Substance, substance))をすると壁が一部消えて右手法(左手法)ではいつか攻略が出来なくなるので、DFS(深さ優先探索)アルゴリズムを考える必要がありそうです。試しに作ってみましたが、かろうじて動くものの酔っ払い運転になっています。
DFS探索(*未完成*)
def dfs():
global count
pos = (get_pos_x(), get_pos_y())
if pos in visited:
return False
visited.add(pos)
if get_entity_type() == Entities.Treasure:
if count>300:
harvest()
else:
use_item(Items.Weird_Substance, substance)
count+=1
return True
for dir in directions:
if can_move(dir):
move(dir)
if dfs():
return True
move(opposite(dir))
return False
def opposite(dir):
return {North: South, South: North, East: West, West: East}[dir]
while True:
plant(Entities.Bush)
substance = get_world_size() * 2**(num_unlocked(Unlocks.Mazes) - 1)
use_item(Items.Weird_Substance, substance)
visited = set()
directions = [North, East, South, West]
dfs()裏技?
左上の実行ボタンを押してドローンの手動操作が可能。
ドローン増やしてみた
world_size=get_world_size()
half_world_size=get_world_size()/2
max_drone = world_size**2 // 32
def AutoCarrot():
for i in range(world_size):
for j in range(world_size):
if can_harvest():
harvest()
elif get_entity_type()!=None:
do_a_flip()
if ((i+j)%half_world_size)>half_world_size*0.6:
plant_crops(Entities.Carrot)
elif ((i+j)%half_world_size)>half_world_size*0.4:
plant_crops(Entities.Sunflower)
elif ((i+j)%half_world_size)==0:
plant_crops(Entities.Tree)
else:
if get_ground_type() == Grounds.Soil:
till()
move(North)
move(East)
if num_drones()<max_drone:
spawn_drone(auto_carrot)
def plant_crops(ent):
if get_ground_type() != Grounds.Soil:
till()
plant(ent)
if (get_water()<0.2):
use_item(Items.Water)
if random()<0.05:
use_item(Items.Fertilizer)
def auto_carrot():
for _ in range(get_pos_y()):
move(South)
for _ in range(get_pos_x()):
move(West)
while True:
AutoCarrot()
auto_carrot()東に移動するタイミングで召喚。can_harvest()がfalseの時はdo_a_flipで遅延を入れて重ならずに収穫を行えるようにしています。
32*32畑+32機のドローンでヒマワリ自動栽培
clear()
change_hat(Hats.Green_Hat)
def setup_farm():
row = num_drones() - 1
move_to(0, row)
auto_farm(row)
def auto_farm(row):
world_size=get_world_size()
half_world_size=get_world_size()/4
while True:
col= get_pos_x()
pos=row+col
if can_harvest():
harvest()
if ((pos)%half_world_size)>half_world_size*0.85:
plant_crops(Entities.Carrot)
elif ((pos)%half_world_size)>half_world_size*0.1:
plant_crops(Entities.Sunflower)
elif ((pos)%world_size)==0:
plant_crops(Entities.Tree)
else:
if get_ground_type() == Grounds.Soil:
till()
move(East)
def plant_crops(ent):
if get_ground_type() != Grounds.Soil:
till()
plant(ent)
if (get_water()<0.4):
use_item(Items.Water)
if random()<0.03:
use_item(Items.Fertilizer)
def move_to(x, y):
size = get_world_size()
curr_x = get_pos_x()
curr_y = get_pos_y()
dx = (x - curr_x + size) % size
dy = (y - curr_y + size) % size
# 最短距離で移動(x方向)
if dx <= size // 2:
for _ in range(dx):
move(East)
else:
for _ in range(size - dx):
move(West)
# 最短距離で移動(y方向)
if dy <= size // 2:
for _ in range(dy):
move(North)
else:
for _ in range(size - dy):
move(South)
def main():
for _ in range(get_world_size()):
spawn_drone(setup_farm)
#1tickの遅延
get_time()
auto_farm(0)
main()段々動けばいいやというメンタルになってくる。現実に支障が出るかもしれない…。


コメント