星田オステオパシー

プログラミング学習日記 2024/01/16〜


2024/01/25 Place-image追加
 Place-image部分をちゃんとWORLDからデータを取り出すように修正、表示部分の場合分けもString-deleteを使って汎用性を上げるように修正


 村建設予定地に空白枠と番号を表示する関数を追加。WORLD-DISPの内容で条件分けして呼び出される。内容は道路候補表示と同じ造りなので改変コピペで


 ↑を更に少しだけ改変コピペしてPlace-town-koho-wakuも作る。今日は宿直無いんだけど、逆に昼間と夜に予定が入っててPCを触る時間が無かった。24時ころに帰宅して、ご飯食べて・・寝るか!と思ったけど気力を絞って改変コピペしてます。毎日少しでも書くのが大事だな、と


 最後にPlace-imageの一番上位レイヤーでWORDL-DISPによる場合分けを書いて終わり。これでようやくお楽しみ、発展カードの実行部分に入っていける。やっぱり表示部分って面倒くさいナリ




2024/01/24 発展カード
 公式ルールをチェック。ふんふん、勝利ポイントはそのままUpdateでScoreにすれば良いな・・・


 盗賊を3回以上退治すると騎士王になるのでPLAYERにスロット作ってやるしかないか・・


 発展カードはいわゆるデッキなのでWORLDにリスト形式で持たせるしかないかな


 枚数が知りたかったので他のページを見たら他にも街道建設と独占があると判明。採用で!


 それぞれの枚数と種別をデータとして作っておいて、そこから指定枚数のシンボルを入れたリストを作ってシャッフルしてやりゃいいか


 ルールを読んで見ると思い違いに気づく。発展カード使用も入手も建設も自ターンに何度も行える模様。ただ、入手した発展カードはそのターンでは使えないと。Phase切り替え時にリストに合体させないといけないな


 ここから夜(Tiny10)の部。発展カードをゲットする関数を書く。この時点では発展カードはターンに1枚しか引けないと思っているので、Main-loop-loopというMain-loop-readとほぼ同じものを作って、ターンに一度しかできない行動の場合の送り先にしてるけど、次回撤廃しないと・・。
 とりあえずいつものパターンで新たなデータを作ってWORLDを更新するだけ


 PLAYERにもWORLDにも同名のD-CARDSを作ってたのでWORLDはD-CARDS-SETに改名する。
 PLAYERのD-CARDSはゲット時には(cons get-cards-list original-d-cards-list)としておいて、PassでPhaseが切り替わる時に合体させる事でそのPhaseでは使用不能にする。Phaseに1枚しか無いと思ってたのでリストにしてないので次回変更しないと。


 表示部分を作る。メニューで手持ちのカード、同種のものは被って表示しないようにリスト化する関数を作って・・




 表示用にString化してリストにして・・


 最後にShuffleして大域変数*d-cards*にする。これはコード冒頭のデータ部分に移動しWORLDの初期値に入れる予定。


 続いて実際に発展カードを使う関数・・これはMainループと同じ作りでサブループとして作ることにしよう。
 発展カードの中でVictoryは勝利点に追加されるというものだからUse-menuからは除外しないといけないのでRemoveで取り除いて、出来上がったリストはList-refで選択するようにして、手持ちからは同じシンボルを一つ取り除いたリストに更新、使ったカードごとにデータを処理する・・と。次回からはKnight、Roads、Discover、Monopolyを作っていこう。Knightを作るためには盗賊が必要なので・・と、結局テストもしないで最後まで作ってしまうノリだけどどうしようっかなぁ・・理論上、今の時点で発展カード以外なら対人で動くはずなんだけど。

 あ、そう言えば村と町の建設候補表示部分を書いてなかったので、ソッチもやらないと。
 


2024/01/23 各施設候補地をどう表示するか
 理想的には破線で表示したかったけど、調べたらそういうオプションは無いので、とりあえずこういう感じで黒枠で表示するしかないか・・

 そう言えばWORLDのDISPにて画面表示の場合分けをしようと思ってるんだけど、どういうふうに書けば良いかテスト。最後の下レイヤーを選択する部分で場合分けするのが良いと判明。
 具体的には1枚上のレイヤーでIfを使ってDISPが(今回は)'ROAD-KOHOだった場合にはPlace-road-wakuを指定、それ以外の場合は更に一枚下のPlace-circleに飛ぶと。


 実験成功

 で、実際のコードですが・・。今回、候補の黒枠に選択用の数字も表示したい。そこでPlace-image/alignでの画像リストと座標リストに両方とも詰め込む方法をやってみた。結局はリストなのでグラも座標もくっつけるだけなのが楽でいい


 実行するとこういう感じ・・うーん・・まあ、分かるけどね?もうちょっとこう・・枠線にキレイに乗せることは出来ないものか?


 先程の書き方だと、どうしてもAlignの設定が共用されてしまうので、設定を変えるには別にするしかない。とは言ってもPlace-road-wakuを複数にするのも管理が面倒なので・・内部で2つ作るのはどうなんだろうか?


 あ、駄目だ。後で実行したほうが返ってきてしまう。その後、色々と試しましたけど結局最初の一気に処理方式に戻しました。オプションで表示場所を変えるんじゃなくて、座標処理用のTate&yokoを専用で作るしか無いな、どうしても表示をイジりたければ。まあ、この辺は最後の微調整で・・・


 というわけで本体に戻した道路候補表示部分はこんな感じ


 1枚上のレイヤーの最後に条件分けでDISPに’ROAD-KOHOがあれば候補枠を表示、なければスルーしてPlace-numberを表示するように、と。


 本体の続き。前回作ったMake-villageを書き換えてMake-townを書いて


 更にMake-roadも改変コピペで書いて・・・



 ここしばらくテストしてないけど、ここまで来たら先に色々と作ってしまおう。残るは発展カード、これは仕様を完全に忘れてるので調べるところからだな〜。あ、もちろん村と町の建設候補の表示も作るけど改変コピペで出来るので。
 それで一応テストして、ちゃんと動くようならば盗賊と騎士部分を作って・・それで対人のシステムは一通り出来るハズなので、COM思考部分を作るも良し、対戦特化でオリジナル要素を足していくも良し、ってな感じで



2024/01/22 Tradeを書く

 まずはTradeのRead部分を書く、ために表示部分。今更ながらドットリストとAssocを使う。意識的に使わないとすぐに忘れるなぁ・・Tradeでは同種4枚のカードが必要なので3枚以下の場合はメニューに表示しないようにする


 というわけで本体のTrade-4to1を書く。Menu1とMenu2を使ってAnswer1とAnswer2を入力、手放したカード4枚を手持ちから引いて、望んだカード1枚を足す。
 で、昨日までのところでCARDS部分を勝手に'(4 4 3 5 2)という普通のリストになってるつもりで書いてたけど構造体CARD形式にしたんだった(-_-;)
 位置固定のリストなので普通のリストにしたら取り回しが楽だったんだけど・・表示部分でWOODとかIRONとかで書いてるから今更の変更は面倒。


 ということで、Struct形式から要素のリスト形式に直せないか?もしかしてマクロが必要か?とか焦ってたんだけど、racket/structに普通にStruct->listがあって大助かり。


 逆にListからStructに戻す方法も無いと困るが・・と思ってたけど、なるほど apply CARD '(1 2 3 4 5) でリストを構造体に出来るのか。助かった〜


 続けて村(CATANでは開拓地)を作るルーチンを作る。まずは同様にメニュー表示部分。これは既に作ってある村を作れる座標を返すvillage-ok-pointsを表示するだけ。
 が!どうせなら画像で表示するマップに破線での「ここに作れまっせ」という候補を表示したい。WORLD-DISPに何らかのフラグを入れて、画像のレイヤーを表示するようにしよう。


 で、Make-village本体を書く。Cross-mapを更新し、Cardsを更新し、Playerを更新しWorldを更新してMain-loop-readへと戻ると、と。

 次回は村の建設候補ポイントを表示するようにしようか、と。これも楽しみだな〜。


 図書館が休みなので自宅で昼間っから書いてました。今日活躍したのは家電の墓場で拾ってきた富士通FMV-77/D。とにかくデカいんだけど、そこそこのパワーと小さいのに使いやすいタッチパッドで書きやすかった・・。ちょっとキーボードの反応は良くないのでしっかり目に押さないといけないが。
 これを膝に載せてパタパタ・・CPUからの発熱で膝も温かい!


2024/01/21 Main-loop-passを書く
 Main-loop-readでPassを選んだ時点で勝利条件のチェックをしないといけないな・・その前にScoreを更新しないといけないか・・って事で書いていく。うーん、場当たり的


 Scoreは全員一気に変更しないといけないのでFor/listで回すんだけど・・そう言えばロンゲストロードをデータとして保持してないので作らないといけない。WORLDにもたせておくべきだったかも知れないけど、結局更新はPhase終了時になるから・・まあ、ここで一緒にやってしまってもエエか。
 あとはPlayerそれぞれの村の数、町の数、発展カード、盗賊撃退の騎士ポイントを足してそれぞれのScoreにする、と。発展カードと騎士ポイントはまた後で・・



 で、やっとこさMain-loop-passが書ける。勝者がいればGame-end関数で終了・・なんだけど、Winner-check?ではBoolしか返ってこないのでGame-endでもまた同様の判定をしないといけないのだった(-_-;)


 というわけでこんな感じ?Winner-check?はPahseをList-refのIndexとしてFor/listで回してBoolのリストを作る。Game-endでもそれを使うんだけど・・これ同時に10点に到達した場合の事を無視してます。うーん、複数対応しておくべきかなぁ・・

 ところでPlayer-listは固定にしておいてCircula-list形式のPhaseをIndexに使って順番を回していくやり方はすごく便利だな。対象になるデータは固定しておいて、捜査する側のデータ?をイジるって覚えておこう。確かDD&Dの時にはキャラクターのリスト自体をCircularで回してたような記憶があるけど・・大変だったんじゃないかな?もはやそれすら覚えてないけど

 次回はTradeルーチンを作っていくか~

 

2024/01/20 資材配布関数の続き
 メニューを表示するのに手持ちのカードやその他の条件ををチェックして、OKなら表示・・としたい。今のところプレイヤー間でのトレードは面倒(やり取りが煩雑になる・・でしょ?)なので実装予定は無い、ので同じカード4枚と望むカード1枚というお上との交換のみを考える。まあでも、人間同士のトレードも、その時だけは口頭で交渉してから相手が承認の入力するだけってすれば行けるかな・・?


 んでまあ、Loopでカウントを回して条件を満たしていた場合には文字列に追加してって最後にCarで表示してるメニュー判定用の数値リスト、Cdr部はString-appendで合体させてメッセージを作ろうかと。


 Main-loopはこんな感じでメニューの数字を入れて・・Menuで作った数値リスト以外の入力はやり直しって事で判定して・・あとは道を作るとか村を作るとかをサブルーチンとして飛ばして実行っ感じで?


 Main-loop-readに入る前にサイコロを振る必要があったので別で書く。ついでにここで懸念の資材追加も行ってしまう。資材追加の更新が面倒なのでリストを1次元化してLoopで回して手持ちに加えていく。この際、加える元をAdd-card-listとしたけど、加えられる方のリストの名前が思いつかなくてClaude2に尋ねる。提案の中でAddend-card-listってのが気に入ったので採用。


 正直、今までで一番役に立ったやり取りだった


 前にも作ったことがあったハズだけど見つからなかったので、また1次元リストを小分けにする関数を書く。ちゃんと整理しておかないとなぁ


 ということで次回からは各サブルーチンを書いていく予定。


 
 ちなみに今回遂に手持ちのノートパソコンからLenovoのX280を持ち出して図書館へ。うーん、Windows11いいやん!我が家のNo2なのでRacketもらくらくで動くしバッテリーも5時間は持ちそうで・・やっぱりお金出して買ったマシンはすごいぜ(6000円くらいだけど)。
 ま、でも前にCametanさんがおっしゃってたように、やっぱりWindowsはフォントが汚いんだよなぁ・・上の画像でも一番上のがWindows、それ以外は宿直先のボロボロレッツノートなんだけど瞭然だからなぁ



2024/01/19 資材配布関数

 実は今回、コードを書き始める前に勝算があった。前回Listにしてパネルの種類、村か町か&プレイヤー、座標ってのをパックにしてて、それぞれが参照先のIndexになってるのでList-setかSet!を使って一発変換が出来る変換器を作れると思ったのだ

 その為に文字列 "v1" って感じのものから数字だけを抜き出して・・と思ったら詰まる。String-refで抜き出した文字列の一部は#\0とかのキャラ?になってしまうのだ。これはString->listのときにも悩まされたしずいぶん前にも引っかかっていたトコロ。結局、String-deleteで小文字アルファベットを消すという方法で抜け出す

 逆に文字列v1から数字だけを消すためのPredが必要なのだが・・通常のnumber?では通じない


 で、こんな感じで作る
 

 さて、いよいよ一括変換部分を作るぞ!と思ったがうまくいかない。
 Set!を使ってList内Listにアクセスして書き換えようと思ったがエラーが出るのでチェックしたら、Set!では束縛したリスト内の要素にはアクセス出来ない模様。マジか!
 うーん、うまい方法だと思ったんだけどなぁ


 しょうがないので別の関数を作って地道にやっていこう。
 例のパックになってるリストの要素を分解して、引数とする関数。
 '((0000) (0000) (0000) (0000))を初期設定のリストとして、Playerの番号(=Index)を使ってIndex番目の(0000)を束縛。
 その(0000)を頭から食わせて同時にCount、Panel-numは変更をかけるパネルの種類でIndexと同じにしてあるので同じCountになったらvtにあるv(村)かt(町)で判定して村なら1枚、町なら2枚を追加してLoopする。


 で、上最終出力部分を改造、For/listで4つあるプレイヤー全員の分と合体させる



 で、上のMake-new-cardsを使って先日作ったドットリストのリストを読み込んで新たなカードセットを返す関数を作る、OK。
 で、いざ実行してみると・・エラー。しまった、村や町を表すv1やt1はシンボルで書いてたのお忘れて文字列ってことにしてしまっていた・・修正が面倒過ぎる


 なので実に無駄だけどこうなったらシンボルを文字列にしてしまう。


 で、それらを組み込んでようやくマップとサイコロの出目でカードが配布される関数が出来上がった。ふぃ〜・・後はこれをWORLD構造体(?)のPLAYER-CARDS部分に入れるようにすればOK。人間なら一発OKの作業もプログラムにすると一苦労だなぁ(いまさら)

 これでようやく、ゲーム部分に入っていくことが出来る!ハズ。


2024/01/17 Katan-O カード配布準備
 昨日作ったFor-corners?を使って、特定のパネルを入れたら四隅の情報を返す関数を作る。今更だけど関数の名前決め問題が深刻。規則を作らないとイカンと思いました。



 そう言えば・・昨日、パネルの順番とラベル(?)の数値をペアにしたけどラベルは文字列のままだったので数値に変換してから合体させる必要があることに気づいた。問題は・・表示の関係で一桁の数値は前に半角スペースを入れてることなんだけど・・まあ、自動で削除してくれるってことは無いか


 自前で (define (string-delete strings character) ... ってのを作ろうかと思ったけど、Pythonの時になんかあったなぁ・・とダメ元でドキュメントを眺めていたらそのものズバリスペースを取り除いてくれる関数があったよ!String-trim。素晴らしい


 一応実験。ちゃんと数字になってる


 とりあえずテスト用にカード配布関数Distribute-material関数を書く。最終的な配布処理はまた別で書くとして(じゃあ名前おかしくない?)・・
 Zero-mapから作ったPanel-list(地形パネルの固定リスト)と、サイコロの出目に対応するNum-list(毎回シャッフルされる)を合成してComposite-listを作り、サイコロの出目DiceとComposite-listのCdr部を比較して同一の要素を抜き出す。で、そのCar部の座標をもとに四隅の情報をリストで取り出して施設があるかどうかをチェック、と。ResultはListのListになってるので、これを加工して対応したパネルの資材を束縛しておいた1-card~4-cardに加えて、PLAYER構造体として返して最終的にWORLDを再構築・・という流れかな。


 テスト。サイコロの出目が4だった場合・・・下段リスト(Cdr部)のインデックス1と6にマッチするので、同じインデックスの上段リスト(Car部)は2と4になる、と。うーん、こんがらがるw


 実際のマップを表示させて検証。何ぃ!?ドヤ文体で解説していたのにバッチリ間違っている!構想としてはラベルが4のパネルをチョイスするはずなのに!どうも雰囲気的にCar部がPanel-listのカードの種別になってるが・・とにかくデバッグだな~


追記 微妙に時間があったのでトライ

 ここが問題だな。よく考えたらCar部は資材の種別チェック用のデータだった。Indexが必要なのだった


 調べるとリスト内のIndexを調べる関数があったので採用。


 ふんふん、良いんじゃないか?


 だが問題発生。ラベルも種別も同じものが複数枚あるので全く一緒の組み合わせだとIndex-ofの性質上最初のものしかヒットしない


 しょうがないのでペア作戦はやめにしてIndex用のリストを作って3要素で構成することに


 これで望む動きが出来た、ケリがついて良かった~

 次は資材カードをそれぞれのPlayerデッキに追加するところを書く!



2024/01/16 Katan-O 道路の続き

 道路建設可能座標は道路から導くのと町村から導くものがあって、要素が被ることがあるので被りを排除して合成する必要がある・・って事で、多分「集合」ってことになるので専用の関数はありそうだけど・・探すほうが面倒なのでそれっぽいのを作る。


 以前に作ったCan-build-road?は全座標を対象にして道が建設可能か?だけを返す関数だったので、それを使って実際の座標のリストを返すものを作る


 で、2つの道路建設可能関数から返った座標のリストを(念の為に)ソートして返す関数、Make-build-road-pointsがようやく完成する!
  簡単だと思って開始したけど結構手間がかかったなぁ〜・・まあ、先の見えないMinimaxとαβカットのことを思えば楽しすぎるけど!



 続いて同じように作りかけだった「全座標の中から町を建設可能な座標を返す関数」を書いて



 いざカードを設定しようと思ってネットを見たら「麦」カードを失念してたのが判明。
 数値は手持ちのカード枚数。テスト用にPLAYER-2-CARDSは全部を0にしておく



 手持ちのカードが施設の建造条件を満たしているかをチェックするための述語を書く。道、村、町、発展カード、それぞれの必要枚数をCheck-patternとして設定して引数に呼び込めるようにして、手持ちのカードと(並びが一緒なので)Loopで突き合わせてResultにCons。終了後に出来たリスト内に#fが1つでもあれば要件を満たしてないので#fを返すという仕組み。テストOK


 ノッてきたのでまだ行くで!(24時過ぎたらNetflixの契約をするつもりだったので待ち時間があったのも理由)。
 今度はPhase最初にパネル四隅に村か町が存在したら、対応してる資源を配布する・・ってのに手をつける。まず、パネルのデータ元がリスト内リストなので一次元化しておく必要があるな・・


 サイコロの出目に対応したパネルのナンバーが必要。これとパネルのリストがペアになって判定をするんだけど・・


 いちいち2つのリストを突き合わせてたら面倒なので、ドットリストで合体させてしまう。そのための実験


 パネルのIndexに対してマップの四隅座標を返す関数を書く。多分もっとエレガントに計算で出せるんだろうけど面倒なので!
 と、ここで24時となりました。あとは・・合成したペアリストのNum部分をDice入力部分で抜き出して、それをリストにしたものをMapかなにかでチェックして、四隅に施設があったらパネル(合成ペアのCar部分)に対応した資材を配分して・・って部分を書くことになるかな。

 思ったよりも進んだけど、思ったよりもやることが多いな〜。水木と宿直Bで快適にRacket使えるので、ガンガン進めるで!

名前:
コメント:

※文字化け等の原因になりますので顔文字の投稿はお控えください。

コメント利用規約に同意の上コメント投稿を行ってください。

 

※ブログ作成者から承認されるまでコメントは反映されません。

  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最近の「プログラミング」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事