2022年 6月 17日
元祖ダイスウォーズには全占領した後リプレイがある。
これをやってみた。
考え方として、まずベタに考えると 1動作につき 1マップ、データ化すると考える。
すると 1マップ最大 X × 55 + Y × 31 = 1705だとして、× 何ターンもデータ化すると量が多すぎる。
しかもダイス増のデータも要るし、キャラクターユニットの情報も要る。
そこで考え方として、初期マップ状態に対する「変化のみをデータ化する」という事を考える。
つまり 1つ占領してマップが変わったら、その占領された国の情報だけをデータ化する。
同様にダイス増もキャラクターユニットも、その変化した国のデータのみを記録する。
次の考えたかとして、HSPは 1データ 4バイトある。
16進数だと FF FF FF FFという事になるけど、10進数だと 2147483648という数までとなる。
2進数や 16進数を扱うのは自分には難しいので、素直に 10進数で考えてみる。
そこで、1つのデータのケタを 4つに分けてつかう。
214 748 364 8 という風に分けて、それぞれデータを入れる。
1つ目~3つ目はデータ、最後の 4つ目はデータの種類を表すフラグデータとする。
これによって HSPで扱う 1データで、この場合は 3つのマップ変化データを扱える。
つまり 3分の1のデータ圧縮と考えられる。
初期
1 2 3 4 5 6 7 8 9 10 |
////////// リプレイ ////////// *rep_ini repb=100000 ; データ dim repd,repb repc=2 ; カウンター repk=0 ; データ位置 return |
リプレイデータは repdになります。
repcは何番目のデータかで、repkは先の通り 1データの何番目のデータかです。
repcが 2からなのは、セーブデータとして repd(0)には repcの値が、repd(1)には repkの値が、それぞれ格納されるためです。
データ書き込み
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
#deffunc rep_add int _repf,int _repn1,int _repn2,int _repn3 ; データ構築 if repc>=repb : return ; 最大書き込み repf=_repf ; データ種類(1=ダイス+、2=勝ち、3=負け) repn1=_repn1 ; 国1 repn2=_repn2 ; 国2 repn3=_repn3 ; 国2のCU移動先 switch repf case 1 ; 国+ if repk=0 { ; 000 000 111 1 repd(repc)+=repf ; データ種類 repd(repc)+=repn1*10 ; 国No. repk+ swbreak } if repk=1 { ; 000 111 000 0 repd(repc)+=repn1*10000 ; 2番目のデータ repk+ swbreak } if repk=2 { ; 111 000 000 0 repd(repc)+=repn1*10000000 ; 3番目のデータ repk=0 ; リセットして次のデータへ repc+ ;: rep_save ; 一旦セーブ判定 swbreak } swbreak case 2 ; 勝ち if repk>0 { ; データ途中 repk=0 repc+ ;: rep_save ; 一旦セーブ判定 } repd(repc)+=repf ; データ種類 repd(repc)+=repn1*10 ; 国1 repd(repc)+=repn2*10000 ; 国2 repd(repc)+=repn3*10000000; 国2のCU移動先 repc+ swbreak case 3 ; 負け if repk>0 { ; データ途中 repk=0 repc+ ;: rep_save ; 一旦セーブ判定 } repd(repc)+=repf ; データ種類 repd(repc)+=repn1*10 ; 国1 repd(repc)+=repn2*10000 ; 国2 repc+ swbreak swend return |
データの 4番目、つまり 1ケタ目のデータは何のデータかを表すフラグになってます。
switch文の repfです。
フラグ 1はダイス増ですね、どの国のダイスが +1されたかだけ記録してます。
repk+によって、1データの何番目に書き込むか指定してます、1~3になってます。
フラグ 2は勝った場合、占領した場合の変化です。
データ 10ケタからは占領した国、10000ケタからは占領された国で、これは 3分割では無くて2分割になってます。
なぜかと言うと、データの最大値が 214 748 364 8であるために、1データ目は 214が最大値になってしまうためで、もし国の最大数が 214以上だと表せなくなります。
もう一つの理由は、1データで一つの戦勝処理を表した方が分かりやすいからだと思います。
フラグ 3は負けた場合のデータです。
データを元にリプレイを表示
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
*replay ; リプレイ repf=0 ; フラグ repc=repb ; カウント rept1=1 ; ダイス+待機時間 rept2=2 ; 戦闘国待機時間 rept3=3 ; 勝敗待機時間 rep_ldn1=0 ; 現プレイヤー rep_ldn2=0 while repf!10 switch repd(repc)\10 case 0 ; end repf=10 swbreak case 1 ; 国ダイス+ rept=rept1 ; 表示時間 if repf=0 { ; データ1 rep_ldn1=(repd(repc)/10)\1000 ; 国No. ldcd(rep_ldn1)+ repf+ swbreak } if repf=1 { ; データ2 rep_ldn1=(repd(repc)/10000)\1000 ; 国No. ldcd(rep_ldn1)+ repf+ swbreak } if repf=2 { ; データ3 rep_ldn1=(repd(repc)/10000000)\1000 ; 国No. ldcd(rep_ldn1)+ repf=0 : repc+ } swbreak case 2 ; 勝ち if repf=0 { ; 攻撃国 kln1=(repd(repc)/10)\100 repf+ : rept=rept2 : rep_ldn1=kln1 swbreak } if repf=1 { ; 防衛国 kln2=(repd(repc)/10000)\1000 repf+ : rept=rept2 swbreak } if repf=2 { ; 勝敗 ldcd(kln2)=ldcd(kln1)-1 : ldcd(kln1)=1 ; ダイス ; cu表情 if ldcu(kln1)>0 : cupf(ldcu(kln1))=1 ; 勝ち if ldcu(kln2)>0 : cupf(ldcu(kln2))=2 ; 負け repeat 1 ; CU移動 kln3=(repd(repc)/10000000)\1000 ; 国2の移動先 if ldcu(kln1)>0 { ldcun=0 ; 一時格納 if ldcu(kln2)>0 : ldcun=ldcu(kln2) ; 一時格納 ldcu(kln2)=ldcu(kln1) ; CU移動 ldcu(kln1)=0 ldcu(kln3)=ldcun ; 入れ替え break } if ldcu(kln2)>0 { if kln3=0 : break ldcu(kln3)=ldcu(kln2) ldcu(kln2)=0 break } loop lpd(kln2)=lpd(kln1) ; 国色を変える repf=0 : repc+ swbreak } swbreak case 3 ; 負け if repf=0 { ; 攻撃国 kln1=(repd(repc)/10)\100 repf+ : rept=rept2 : rep_ldn1=kln1 swbreak } if repf=1 { ; 防衛国 kln2=(repd(repc)/10000)\1000 repf+ : rept=rept2 swbreak } if repf=2 { ; 勝敗 ldcd(kln1)=1 ; cu表情 if ldcu(kln1)>0 : cupf(ldcu(kln1))=2 ; 負け if ldcu(kln2)>0 : cupf(ldcu(kln2))=1 ; 勝ち repf+ : rept=rept3 swbreak } if repf=3 { ; リセット repf=0 : repc+ : rept=1 } swbreak swend ; cu表情のリセット if lpd(rep_ldn1)!lpd(rep_ldn2) { repeat ldb,1 : ldn=cnt if lpd(ldn)!lpd(rep_ldn1) : continue if ldcu(ldn)=0 : continue cupf(ldcu(ldn))=0 ; フラットに loop rep_ldn2=rep_ldn1 } repeat rept redraw 0 sc_mput redraw 1 await 100 loop wend return |
データの 1ケタ目をフラグ repfとして、同じように switch文で分岐処理します。
1はダイス増、2は占領、3は負け処理です。
キャラクターユニットの移動は、元のマップからの変化でのみ処理してます。
つまり、もしどこかで間違えると、ずっと間違ったまま処理されます。
少しややこしいのは、キャラクターユニットの表情の変化です。
表情の値は cupfです。
詳細は忘れましたけど、その国の番が回ってきた時に表情をフラットにするのに苦心したと思います。
これでリプレイのデータ量は、大体 10000前後~多くても 30000以内くらいです。
10000データという事は 40000バイト、つまり 4MBです。
今の所セーブ箇所が 8個になる予定なので、× 8で最大 32MBくらいになると思います。