目次: ゲーム
大昔にちょっとだけやって中断していたゲーム「農家はREPLACE()されました」を9割位までクリアしました。
実績の残り2個はランキングに載れ的なやつで、やる気が起きなかったのでこれでおしまいですね。
序盤は適当にループを回して、文法系を全開放(list, dict, set_world_sizeなど)、迷路までの作物、複数ドローンを開放します。中盤は各種作物に最適化して組んだプログラムを動かす&放置&資源がたまったらレベルを適宜開放、を繰り返します。実装したらやることがなくなっちゃう。
プログラムは最大レベル(農場サイズ32x32、ドローン32機)に合わせて決め打ち実装した方が効率的で速いです。が、中盤は農場サイズやドローン数が少なく、32x32決め打ち実装だと動かなくて辛いです。個人的には農場サイズやドローン数が可変にできるように実装した方がゲーム進行的には楽だと思いました。
カボチャとサボテンの実装を紹介しようと思います。一応、カボチャマスターとサボテンマスターは取れるはず、たぶん。
各ドローンは1機1行を担当します。西から東の一方向にスキャンし続け、割れたカボチャがあったら植え直し、一列全部がきれいなカボチャになったらドローンの処理おしまいです。これを全行に対して実行します。
最初のドローンは北に移動しながらドローンを複製できるだけ複製して、複製の上限に達したら自分も1行担当します。全面カボチャになって、ドローンが最初のドローン1機だけになったら収穫します。
def cond():
a = num_items(Items.Power) > MIN_POWER
b = num_items(Items.Carrot) > MIN_CARROT
c = num_items(Items.Pumpkin) < MAX_PUMPKIN
return a and b and c
def get_pline():
pline = 0
for i in range(get_world_size()):
if get_entity_type() == Entities.Pumpkin:
pline += 1
move(North)
return pline
def drone():
plist = []
pnum = 0
for i in range(get_world_size()):
plist.append(False)
while True:
if get_entity_type() == Entities.Grass:
till()
if get_entity_type() == Entities.Pumpkin and can_harvest():
if not plist[get_pos_x()]:
plist[get_pos_x()] = True
pnum += 1
if pnum == get_world_size():
return
else:
plant(Entities.Pumpkin)
if get_water() < 0.5:
use_item(Items.Water)
move(East)
def pumpkin():
clear()
while cond():
if not spawn_drone(drone):
drone()
if get_pline() == get_world_size():
while num_drones() > 1:
pass
harvest()
move(North)
動作を見たらすぐ気づくと思いますが、効率は良くないです。特に最初のドローンがスキャンする処理が長引くと、複数ドローンが出せない時間も長引いてしまいボトルネックになります。
全面にサボテンを植えて、東北側に大きなサボテン、南西側に小さなサボテンを集めるようにソートし、収穫します。ヒントにある通り、行ごとにソート、列ごとにソートの順に実行すれば全面ソート済みになります。
コードはこんな感じ。もっと短くできそうですけど気にしない。
def move_to(x, y):
ws = get_world_size()
dirx = East
if (x - get_pos_x() + ws) % ws > (ws / 2):
dirx = West
diry = North
if (y - get_pos_y() + ws) % ws > (ws / 2):
diry = South
while get_pos_x() != x:
move(dirx)
while get_pos_y() != y:
move(diry)
def cond():
a = num_items(Items.Power) > MIN_POWER
b = num_items(Items.Pumpkin) > MIN_PUMPKIN
c = num_items(Items.Cactus) < MAX_CACTUS
return a and b and c
def is_ready(l):
for i in range(get_world_size()):
if l[i] == -1:
return False
return True
def is_sorted(l):
for i in range(get_world_size() - 1):
if l[i] > l[i + 1]:
return False
return True
def get_west_x():
return (get_pos_x() - 1 + get_world_size()) % get_world_size()
def get_east_x():
return (get_pos_x() + 1 + get_world_size()) % get_world_size()
def get_south_y():
return (get_pos_y() - 1 + get_world_size()) % get_world_size()
def get_north_y():
return (get_pos_y() + 1 + get_world_size()) % get_world_size()
def swap_item(l, a, b, dir):
t = l[a]
l[a] = l[b]
l[b] = t
swap(dir)
def plant_water():
if get_entity_type() == Entities.Grass:
till()
plant(Entities.Cactus)
if get_water() < 0.5:
use_item(Items.Water)
def drone_x(st):
move_to(0, st)
xlist = []
for i in range(get_world_size()):
xlist.append(-1)
while cond() and not is_ready(xlist):
plant_water()
xlist[get_pos_x()] = measure()
move(East)
move_to(0, st)
vmax = get_world_size() - 1
while cond():
if is_sorted(xlist):
return
for i in range(vmax):
if get_pos_x() > 0 and xlist[get_west_x()] > xlist[get_pos_x()]:
swap_item(xlist, get_west_x(), get_pos_x(), West)
move(East)
for i in range(vmax):
if get_pos_x() < get_world_size() - 1 and xlist[get_east_x()] < xlist[get_pos_x()]:
swap_item(xlist, get_east_x(), get_pos_x(), East)
move(West)
move(East)
vmax -= 2
def drone_y(st):
move_to(st, 0)
ylist = []
for i in range(get_world_size()):
ylist.append(-1)
while cond() and not is_ready(ylist):
ylist[get_pos_y()] = measure()
move(North)
vmax = get_world_size() - 1
while cond():
if is_sorted(ylist):
return
for i in range(vmax):
if get_pos_y() > 0 and ylist[get_south_y()] > ylist[get_pos_y()]:
swap_item(ylist, get_south_y(), get_pos_y(), South)
move(North)
for i in range(vmax):
if get_pos_y() < get_world_size() - 1 and ylist[get_north_y()] < ylist[get_pos_y()]:
swap_item(ylist, get_north_y(), get_pos_y(), North)
move(South)
move(North)
vmax -= 2
def area(func, start, end):
for i in range(start, end):
spawn_drone(func, i + 1)
func(start)
while num_drones() > 1:
pass
def cactus():
clear()
while cond():
for i in range(0, get_world_size() - 1, max_drones()):
area(drone_x, i, min(get_world_size() - 1, i + max_drones() - 1))
for i in range(0, get_world_size() - 1, max_drones()):
area(drone_y, i, min(get_world_size() - 1, i + max_drones() - 1))
harvest()
ソートアルゴリズムは何でも良いですが、このゲームの大きな制約が2つあって、
おそらくバブルソート系のアルゴリズムを選択せざるを得ないでしょう。上記の実装ではシェイカーソートを使いました。シェイカーソートの存在は知ってましたが、実用的じゃないので実装したことなかったです。改めて実装してみるとなかなか新鮮でした。
この記事にコメントする
目次: ゲーム
1日だけやって放置していたぽこあポケモンをクリア(=スタッフロールが流れるイベントを終わらせた)しました。プレイ時間カウントを確認すると65時間でしたが、絶対そんなにやってないぞ……夜に始めて寝落ちして、何度か長時間放置してしまった影響が大きいかも。
地形を構成するブロックを壊したり積んだり、湧いてくるアイテムを集めて他のアイテムを作ったりします。ポケモンたちのお願いを叶えて住みよい環境にすることも重要です。一応クリアはあるものの、基本的には何をしても良く、終わりがありません。無限です。
マインクラフトはほぼやったことないので間違ってるかもですが、基本的なシステムは一緒だと思います。マインクラフトはキャラクターがあまりかわいくないデザインですが、ぽこポケは主人公のメタモンもかわいいし、懐いてくるポケモン達がかわいいです。あと戦いの要素がありません。ゾンビに突然攻撃されて死んだりする不快な現象は発生しません。
そういえば、マインクラフトを初めて見たときは自分の中のゲームの定義が揺らぎました。私はゲーム=ルール+目的のセットだと認識していたので、例えば「積み木ゲーム」なら「積み木(=ルール)で〇〇を作ろう(=目的)」みたいなもんを想像するんです。
しかしマインクラフトやぽこポケは「積み木」だけそのまま渡されたようなもので、とても斬新でしたし、これで何をするのでしょう……?とわからない不思議なゲームでもありました。今だにマインクラフトはペイントツールもしくはシミュレータの類と言ってくれたほうがしっくりきます。
でもそれは街作りシミュレータだって一緒でしょ、何が違うの?と言われるとうまく説明できないんですけど、自由度の差なんですかね?
この記事にコメントする
| < | 2026 | > | ||||
| << | < | 05 | > | >> | ||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| - | - | - | - | - | 1 | 2 |
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 | - | - | - | - | - | - |
21年12月28日
26年5月3日
26年4月29日
26年4月7日
23年5月15日
26年2月8日
26年4月4日
26年4月5日
26年3月20日
26年3月6日
21年5月22日
26年3月2日
26年3月10日
22年4月13日
07年11月1日
20年10月23日
18年7月21日
02年11月22日
22年11月11日
07年11月2日
wiki
Linux JM
Java API
2002年
2003年
2004年
2005年
2006年
2007年
2008年
2009年
2010年
2011年
2012年
2013年
2014年
2015年
2016年
2017年
2018年
2019年
2020年
2021年
2022年
2023年
2024年
2025年
2026年
過去日記について
アクセス統計
サーバ一覧
サイトの情報合計:
本日: