OSDN Git Service

PHP Notice対応
[trpgtools-onweb/AjaxChat.git] / lib / trpg.php
1 <?php
2 /*
3  Ajax Chat for TRPG ver.2.6.2
4  (c)2007-2009 Cake All Rights Reserved.
5  Mail : cake_67@users.sourceforge.jp
6  Home : http://trpgtools-onweb.sourceforge.jp/
7  */
8
9 /*
10  * 入力内容をダイス変換
11  */
12 function convert_dice($string) {
13     // 基本ダイス変換
14         // [2d6+5@u(l)o4cr6mfz1]/3
15     if (preg_match("/(.*)[[]([0-9]+)(d)([0-9]+)([-\+\*\/\s]*[0-9-\+\*\/\s]*)@?([ul][0-9]+s?o?)?(cr?[0-9\-]+m?)?(f?z?[0-9\-]*)[\]]([\/\*]{0,1}[1-9]*)(.*$)/i", $string, $dice)) {
16         $GLOBAL['AJAX_CHAT_TRPG']['count_one'] = true;
17         $dice_result = dice_convert($dice[2], $dice[4], $dice[5], $dice[6], $dice[7], $dice[8], $dice[9]);
18         $string = $dice[1].$dice_result.$dice[10];
19     }
20     // 市販ルール対応
21     // SWレーティング振り
22     elseif (USE_CONSUMER_RULES) {
23         if(preg_match("/(.*)[[]([0-9]{0,})([rl])([0-9]{1,})([-\+\*\/\s]{0,}[0-9-\+\*\/\s]{0,})[\]](.*$)/i", $string, $rating)) {
24             $dice_result = dice_convert($rating[2], $rating[4], $rating[5], "", "", "", "", $rating[3]);
25             $string = $rating[1].$dice_result.$rating[6];
26         }
27     }
28
29     return $string;
30 }
31
32
33 /**************
34  * ダイス
35  **************/
36
37 /*
38  * ダイス計算
39  */
40 function dice_convert($dicenum, $dicenumber, $revision, $pickup, $c, $f, $finalcal, $dice_type = "d") {
41     $dice_hidden = false;
42
43     // 修正値計算用再変換
44     $revision = preg_replace("/\s/","+",$revision);
45
46     // 返り値用:元のダイス
47     $dice = "[%s".$dice_type.$dicenumber.$revision;
48     if ($dice_type == "d") {
49         if ($pickup || $c || $f) {
50             $dice .= "@".$pickup.$c. $f;
51         }
52     }
53     $dice .= "]";
54     $row_dice = $dice;
55     $dice = sprintf($row_dice, $dicenum).$finalcal;
56
57     // 市販ルール用ダイス置換
58     if (DICE_MAX && USE_CONSUMER_RULES) {
59         require_once './lib/consumer_rule.php';
60
61         // 「ダイス変換はブラックボックス」ルールの場合
62         // 改修の際は厳守してください
63         if ($dice_type == "r") {
64             $dice_hidden = true;
65         }
66  
67         // SW
68         if ($dice_type == "r") {
69             $rating = intval($dicenumber);
70             if (!is_int($rating) || $rating < 0 || $rating > 100) {
71                 return $dice.'<font style="color:#'.MAIN_TEXTCOLOR.';">(レーティングの指定が正しくありません)</font>';
72                 }
73             if ($dicenum) $c = "cr".$dicenum."-";
74             $f = "fz2";
75             $dicenum = 2;
76             $dicenumber = 6;
77         }
78                 // G
79                 // S
80                 // DC
81                 // NW
82     }
83
84     // ダイスを振る
85     $rolling = "";
86     $total_sum = 0;
87     $value = 0;
88     $roll = array();
89     $arr_dicenum = array(0 => $dicenum);
90
91     $total_success = 0;
92     for ($i=0;$i<10;$i++) {
93         if (!$arr_dicenum[$i]) {
94             $arr_dicenum[$i] = $dicenum;
95         }
96         // ダイスロール
97         list($error, $roll[$i]) = dice_main($arr_dicenum[$i], $dicenumber, $revision, $c, $f, $pickup);
98         if ($error) {
99             return $dice.'<font style="color:#'.MAIN_TEXTCOLOR.';">'.$error.'</font>';
100         }
101
102         // 市販ルール対対応:ダイス合計値計算
103         if (USE_CONSUMER_RULES) {
104             $roll[$i]['dice_sum_disp'] = $roll[$i]['dice_sum'];
105
106             if ($dice_hidden) {
107                 $roll[$i]['dice_sum_disp'] = null;
108             }
109
110             // SW
111             if ($dice_type == "r") {
112                 $roll[$i]['dice_sum'] = convert_sw_rating($rating, $roll[$i]['dice_sum']);
113             }
114         }
115
116         // ダイス出力準備(1)
117         $rolling .= $roll[$i]['dice_list'] ." ";
118         if ($pickup) {
119             $rolling .= $roll[$i]['success_num'].'個成功 ';
120             $total_success += $roll[$i]['success_num'];
121             if ($roll[$i]['clit_num']) {
122                 $rolling .= $roll[$i]['clit_num'].'個クリティカル ';
123             }
124
125         }
126         if (!$dice_hidden) {
127             $rolling .= "= ".(int)$roll[$i]['dice_sum'];
128             $total_sum += (int)$roll[$i]['dice_sum'];
129         } elseif ($dice_type == "r") {
130             $rolling .= "= " . array_sum($roll[$i]['d_result']);
131             $rolling .= " →";
132             $total_sum += (int)$roll[$i]['dice_sum'];
133         }
134
135         // クリティカルで振り足す
136         if ($roll[$i]['flg_c'] && $roll[$i]['rolling_num']) {
137             // サーバの安全のため、規定数以上は手動振り足し [回数の基準はブックですw]
138             if ($i != 9) {
139                 $rolling .= " = ";
140                 if ($pickup) {
141                     $rolling .= $roll[$i]['rolling_num'].'個';
142                 }
143                 $rolling .= C_ROLLING_MSG." ";
144             } else {
145                 if ($roll[$i]['clit_num']) { 
146                     $add_rolling_num = $roll[$i]['clit_num'];
147                 } else {
148                     $add_rolling_num = $dicenum;
149                 }
150                 $rolling .= "***もう一回".sprintf($row_dice, $add_rolling_num)."を振り足してください***";
151             }
152
153             $j = $i+1;
154             if ($pickup && $roll[$i]['clit_num']) {
155                 $arr_dicenum[$j] = $roll[$i]['clit_num'];
156             } else {
157                 $arr_dicenum[$j] = $arr_dicenum[$i];
158             }
159
160      // 振り足さない場合ループを抜ける
161         } else {
162             break;
163         }
164     }
165
166     if (!$dice_hidden && count($arr_dicenum) > 1) {
167         $rolling .= ' = トータル';
168         if ($total_success) {
169             $rolling .= " ". $total_success.'個成功,';
170         }
171         if ($total_sum) {
172             $rolling .= " 合計 ". $total_sum;
173         }
174     }
175     // 修正値を加える
176     // ファンブルは0点で1回目のダイスがファンブルの場合は修正値も入らない
177     if($revision && (!F_ZERO || !$roll[0]['flg_f'])) {
178         list($value, $error) = calc_value($total_sum, $revision);
179     } else {
180         $value = $total_sum + $revision;
181     }
182     if ($error) {
183         return $dice.'<font style="color:#'.MAIN_TEXTCOLOR.';">'.$error.'</font>';
184     }
185
186     // 最終値の乗除算
187     if ($finalcal) {
188         if (preg_match("/^(\*)([0-9]{1,})$/", $finalcal, $finalmalti)) {
189             $value = $value * $finalmalti[2];
190         } elseif (preg_match("/^\/([0-9]+)$/", $finalcal, $finaldev)) {
191             if ($finaldev[1] != 0) {
192                 $value = $value / $finaldev[1];
193             } else {
194                 return $dice."(0では割れません)";
195             }
196         } else {
197             return $dice.'<font style="color:#'.MAIN_TEXTCOLOR.';">'."(最終乗除算の設定が不正です)</font>";
198         }
199     }
200
201     // ダイス出力準備(2)
202     $dice .= " = ";
203     if ($finalcal) $dice = $dice."[";
204     $dice .= $rolling;
205
206     if($revision) {
207         if (F_ZERO && $roll[0]['flg_f'] && !$pickup) {
208             $revision = "<s>".$revision."</s>";
209         }
210         $dice .= " ".$revision;
211     }
212     if ($finalcal) $dice .= "]".$finalcal;
213     if ($value !== false) {
214         $dice .= " = ".round($value, 1);
215     }
216     $dice .= '</span> ';
217     $dice = '; font-weight: bold;">'.$dice;
218     // クリティカル・ファンブルの場合強調色
219     // 回ってファンブルで止まった場合はクリティカル扱い
220     if ($roll[0]['flg_c']) {
221         $dice = ' <span style="color:#'.C_COLOR. $dice;
222     } elseif ($roll[0]['flg_f']) {
223         $dice = ' <span style="color:#'.F_COLOR. $dice;
224     } else {
225         $dice = ' <span style="color:#'.DICE_COLOR. $dice;
226     }
227
228     return $dice;
229 }
230
231 /*
232  * ダイス本体
233  */
234 function dice_main($dicenum, $dicenumber, $revision, $c, $f, $pickup) {
235     $error = '';
236     $d_result = array();
237     $dice_sum = 0;
238     $flg_m = '';
239
240     if ((int)DICE_MAX > 1000) {
241         $error = ' (ダイス数の設定が誤っています。1000個以下にしてください)]';
242     } elseif ($dicenum >= 1 && $dicenum <= (int)DICE_MAX) {
243         if ($dicenumber >= 2 && $dicenumber <= 100) {
244             // クリティカル判定
245             if (preg_match("/^c(r)?([0-9\-]+)(m)?$/i", $c, $matches_c)) {
246                 $flg_m = $matches_c[3];
247             }
248
249             // ファンブルは0点の場合
250             if (preg_match("/^fz([0-9]+)([\-]*)$/i", $f)) {
251                 define(F_ZERO, true);
252             } else {
253                 define(F_ZERO, false);
254             }
255
256             // roll
257             mt_srand((double) microtime() * 1000000);
258
259             // 一定値以上/以下の出目をカウント
260             if ($pickup) {
261                 if (!preg_match("/^([ul])([0-9]+)(o)?$/i", $pickup, $matches_p)) {
262                     error_log('ダイスの指定が不正です');
263                 }
264                 $pickup_v = $matches_p[1];
265                 $pickup_number = $matches_p[2];
266                 $pickup_one = $matches_p[3];
267             }
268             $dice_sum = 0;
269             $success_num = 0;
270             $clit_num = 0;
271             $rolling_num = 0;
272             $flg_c = false;
273             $flg_r = false;
274             $flg_f = false;
275
276             // 1個ずつダイスロール
277             for ($i=0; $i<$dicenum; $i++) {
278                 $d_result[$i]['result'] = mt_rand(1, $dicenumber);
279
280                 // 一定値以上/以下の出目をカウント
281                 if ($pickup) {
282                     // クリティカル/ファンブルの検出
283                     list($d_result[$i]['flg_c'], $flg_r, $d_result[$i]['flg_f']) = cf_check($d_result[$i]['result'], $c, $f);
284                     if (!$flg_c && $d_result[$i]['flg_c']) {
285                         $flg_c = true;
286                     }
287
288                     // 成否判断
289                     $d_result[$i]['success'] = false;
290                     if ((stristr($pickup_v, 'u') && $d_result[$i]['result'] >= $pickup_number)
291                             || (stristr($pickup_v, 'l') && $d_result[$i]['result'] <= $pickup_number)) {
292                         $d_result[$i]['success'] = true;
293                         $success_num++;
294
295                         // クリティカル
296                         if ($d_result[$i]['flg_c']) {
297                             $clit_num++;
298                             // クリティカル振り足し
299                             if ($flg_r) {
300                                 $rolling_num++;
301                             }
302                         }
303
304                         // クリットは最大の出目扱い
305                         if ($d_result[$i]['flg_c'] && $flg_m) {
306                                 $d_result[$i]['add_number'] = (int)$dicenumber;
307                         } else {
308                                 $d_result[$i]['add_number'] = (int)$d_result[$i]['result'];
309                         }
310
311                         // 合計値
312                         //最大値のみ加算する場合
313                         if ($pickup_one) {
314                             if ((int)$d_result[$i]['add_number'] > (int)$d_result['result_max']) {
315                                 $d_result['result_max'] = (int)$d_result[$i]['add_number'];
316                             }
317                         // 成功値全部加算する場合
318                         } else {
319                             $dice_sum += $d_result[$i]['add_number'];
320                         }
321                     }
322
323                 // 通常のダイスロール
324                 } else {
325                     $dice_sum += $d_result[$i]['result'];
326                 }
327
328                 // 出目出力
329                 if ($i != 0) {
330                     $dice_list .= ", ";
331                 } else {
332                    $dice_list = "(";
333                 }
334                 // 成功ダイスは色を変える
335                 if ($pickup) {
336                     if ($d_result[$i]['success']) {
337                         $d_result[$i]['result'] = '<font color="#'.S_COLOR.'">'.$d_result[$i]['result'].'</font>';
338                     }
339                 }
340                 $dice_list .= $d_result[$i]['result'];
341             }
342             $dice_list .= ")";
343
344             // 合計値:最大値のみ加算する場合
345             if ($pickup_one) {
346                  $dice_sum = $d_result['result_max'];
347             }
348             // クリティカル・ファンブルの判定:通常ダイス
349             if ($pickup=='' && ($c || $f)) {
350                 list($flg_c, $flg_r, $flg_f) = cf_check($dice_sum, $c, $f);
351
352                 if ($flg_c && $flg_r) {
353                     $rolling_num = 1;
354                 }
355
356                 if (F_ZERO && $flg_f) {
357                     $dice_sum = 0;
358                 }
359             }
360
361         } else {
362             $error = ' (d2~d100の範囲で指定してください)';
363         }
364     } else {
365         $error = ' (ダイスの数は1から'.DICE_MAX.'の間で指定してください)';
366     }
367
368     $d_result['dice_sum'] = $dice_sum;
369     $d_result['success_num'] = $success_num;
370     $d_result['clit_num'] = $clit_num;
371     $d_result['rolling_num'] = $rolling_num;
372     $d_result['dice_list'] = $dice_list;
373     $d_result['d_result'] = $d_result;
374     $d_result['flg_c'] = $flg_c;
375     $d_result['flg_f'] = $flg_f;
376
377     return array($error, $d_result);
378 }
379
380 /*
381  * ダイス修正値の計算
382  */
383 function calc_value($dice_sum, $revision) {
384     $multi = preg_match("/\*/", $revision);
385     $dev = preg_match("/\//", $revision);
386     $add = preg_match("/\+/", $revision);
387     $subtract = preg_match("/\-/", $revision);
388
389     // +-*/で分割
390     $revision = preg_replace("/\+/","<>+<>",$revision);
391     $revision = preg_replace("/\-/","<>-<>",$revision);
392     $revision = preg_replace("/\*/","<>*<>",$revision);
393     $revision = preg_replace("/\//","<>/<>",$revision);
394     $parts = explode("<>",$revision);
395     array_splice($parts, 0, 1, $dice_sum);
396
397     // 乗算&除算
398     if ($multi || $dev) {
399         foreach ($parts as $k => $v) {
400             if ($v != '0' && $v == '*') {
401                 if (!preg_match("/[0-9]{1,}/", $parts[$k+1])) $error = "演算子が連続してます";
402                 $flg = $k;
403                 array_splice($parts, $k+1, 1, $parts[$k-1] * $parts[$k+1]);
404                 array_splice($parts, $k-1, 1, 0);
405                 array_splice($parts, $k, 1, $parts[$k-2]);
406                 array_splice($parts, $k-2, 1, '+');
407             }
408             if ($v != '0' && $v == '/') {
409                 if (!preg_match("/[0-9]{1,}/", $parts[$k+1])) $error = "演算子が連続してます";
410                 array_splice($parts, $k+1, 1, $parts[$k-1] / $parts[$k+1]);
411                 array_splice($parts, $k-1, 1, 0);
412                 array_splice($parts, $k, 1, $parts[$k-2]);
413                 array_splice($parts, $k-2, 1, '+');
414             }
415         }
416     }
417
418     // 加減算
419         foreach ($parts as $k => $v){
420             if ($v != '0') {
421                 if ($v == '+') {
422                     if (!preg_match("/[0-9]{1,}/", $parts[$k+1]))  $error = "演算子が連続してます";
423                     array_splice($parts, 0, 1, $parts[0] + $parts[$k+1]);
424                 } elseif ($v == '-') {
425                     if (!preg_match("/[0-9]{1,}/", $parts[$k+1]))  $error = "演算子が連続してます";
426                     array_splice($parts, 0, 1, $parts[0] - $parts[$k+1]);
427                 }
428             }
429         }
430
431     return array($parts[0], $error);
432 }
433
434 /*
435  * クリティカル・ファンブルの検出
436  */
437 function cf_check($dice_sum, $c, $f) {
438     if ($c || $f) {
439         if ($c && preg_match("/^c(r)?([0-9]+)([\-]*)(m)?$/i", $c, $clit)) {
440             if ($clit[3] && $dice_sum >= $clit[2]) {
441                 $flg_c = true;
442             } elseif (!$clit[3] && $dice_sum == $clit[2]) {
443                 $flg_c = true;
444             } else {
445                 $flg_c = false;
446             }
447             if ($flg_c) {
448                 if ($clit[1]) {
449                     $flg_r = true;
450                 }
451             }
452         }
453         if ($f && preg_match("/^[fF][zZ]{0,1}([0-9]{1,})([\-]{0,})$/i", $f, $famble)) {
454             if ($famble[2] && $dice_sum <= $famble[1]) {
455                 $flg_f = true;
456             } elseif (!$famble[2] && $dice_sum == $famble[1]) {
457                 $flg_f = true;
458             } else {
459                 $flg_f = false;
460             }
461         }
462     }
463     return array($flg_c, $flg_r, $flg_f);
464 }
465
466 ?>