コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2026年5月3日 >>> 2026年4月20日
link もっと後

2026年5月3日

農家はREPLACE()されました、を9割クリア

目次: ゲーム

大昔にちょっとだけやって中断していたゲーム「農家はREPLACE()されました」を9割位までクリアしました。


「農家は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つあって、

  • 隣接するサボテン同士しか交換できない
  • ドローンの移動が遅い

おそらくバブルソート系のアルゴリズムを選択せざるを得ないでしょう。上記の実装ではシェイカーソートを使いました。シェイカーソートの存在は知ってましたが、実用的じゃないので実装したことなかったです。改めて実装してみるとなかなか新鮮でした。

編集者:すずき(2026/05/06 19:16)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2026年4月29日

ぽこあポケモンをクリア

目次: ゲーム

1日だけやって放置していたぽこあポケモンをクリア(=スタッフロールが流れるイベントを終わらせた)しました。プレイ時間カウントを確認すると65時間でしたが、絶対そんなにやってないぞ……夜に始めて寝落ちして、何度か長時間放置してしまった影響が大きいかも。

ぽこあポケモンの感想

地形を構成するブロックを壊したり積んだり、湧いてくるアイテムを集めて他のアイテムを作ったりします。ポケモンたちのお願いを叶えて住みよい環境にすることも重要です。一応クリアはあるものの、基本的には何をしても良く、終わりがありません。無限です。

マインクラフトはほぼやったことないので間違ってるかもですが、基本的なシステムは一緒だと思います。マインクラフトはキャラクターがあまりかわいくないデザインですが、ぽこポケは主人公のメタモンもかわいいし、懐いてくるポケモン達がかわいいです。あと戦いの要素がありません。ゾンビに突然攻撃されて死んだりする不快な現象は発生しません。

ゲームってなんだっけ……?

そういえば、マインクラフトを初めて見たときは自分の中のゲームの定義が揺らぎました。私はゲーム=ルール+目的のセットだと認識していたので、例えば「積み木ゲーム」なら「積み木(=ルール)で〇〇を作ろう(=目的)」みたいなもんを想像するんです。

しかしマインクラフトやぽこポケは「積み木」だけそのまま渡されたようなもので、とても斬新でしたし、これで何をするのでしょう……?とわからない不思議なゲームでもありました。今だにマインクラフトはペイントツールもしくはシミュレータの類と言ってくれたほうがしっくりきます。

でもそれは街作りシミュレータだって一緒でしょ、何が違うの?と言われるとうまく説明できないんですけど、自由度の差なんですかね?

編集者:すずき(2026/05/06 02:41)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2026年5月3日 >>> 2026年4月20日
link もっと後

管理用メニュー

link 記事を新規作成

<2026>
<<<05>>>
-----12
3456789
10111213141516
17181920212223
24252627282930
31------

最近のコメント20件

  • link 26年1月23日
    すずきさん (01/29 09:48)
    「おおー、そんな昔からなんですね。歴史感じ...」
  • link 26年1月23日
    hdkさん (01/27 19:53)
    「#! はUNIX v8からだったってWi...」
  • link 24年12月9日
    すずきさん (01/18 15:45)
    「Thank you for your i...」
  • link 24年12月9日
    Up2Uさん (01/15 12:57)
    「Hi I also find the p...」
  • link 25年12月18日
    すずきさん (12/23 23:51)
    「良く見たらksys_read()でfil...」
  • link 25年12月18日
    すずきさん (12/23 23:15)
    「ですね、まあpread+readだと話が...」
  • link 25年12月18日
    hdkさん (12/21 08:34)
    「昔試しにデバイスドライバーを作ったことが...」
  • link 25年11月28日
    hdkさん (12/04 08:10)
    「あれ、停止直前くらいの時のトルクコンバー...」
  • link 25年11月28日
    すずきさん (12/03 11:24)
    「トルクコンバーターがいてエンブレは掛かり...」
  • link 25年11月28日
    hdkさん (12/02 08:02)
    「"停止直前に急にエンブレがほぼゼロになる...」
  • link 25年10月6日
    すずきさん (10/10 13:14)
    「ですね。ccはもはやコンパイラというより...」
  • link 25年10月6日
    hdkさん (10/10 08:27)
    「ただのHello, worldでも試して...」
  • link 25年9月29日
    すずきさん (10/03 00:29)
    「なんと、メタパッケージ入れてなかったです...」
  • link 25年9月29日
    hdkさん (10/02 06:51)
    「あれ、dkmsは自動ビルドされるのが便利...」
  • link 20年8月24日
    すずきさん (08/30 22:06)
    「ですね、自分も今はPulseAudioを...」
  • link 20年8月24日
    hdkさん (08/29 09:32)
    「ALSA懐かしい... PulseAud...」
  • link 16年2月14日
    すずきさん (08/04 01:31)
    「お役に立ったようでしたら幸いです。」
  • link 16年2月14日
    enc28j60さん (08/03 17:40)
    「ちょうど詰まっていたところです。\n非常...」
  • link 25年7月20日
    すずきさん (07/30 00:10)
    「ギクシャクするのは減速時の2速シフトダウ...」
  • link 25年7月20日
    hdkさん (07/29 07:38)
    「2速発進でギクシャクするんですか? 面白...」

最近の記事3件

  • link 21年12月28日
    すずき (05/06 19:21)
    「[ゲーム - まとめリンク] 目次: ゲームNintendo DSを買ったパネルでポンDS最近の朝はパネポンDS聖剣伝説DSチ...」
  • link 26年5月3日
    すずき (05/06 19:16)
    「[農家はREPLACE()されました、を9割クリア] 目次: ゲーム大昔にちょっとだけやって中断していたゲーム「農家はREPL...」
  • link 26年4月29日
    すずき (05/06 02:41)
    「[ぽこあポケモンをクリア] 目次: ゲーム1日だけやって放置していたぽこあポケモンをクリア(=スタッフロールが流れるイベントを...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 2025年
open/close 2026年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www2.katsuster.net
RDFファイル RSS 1.0

最終更新: 05/06 19:21