forked from YAYA-shiori/yaya-shiori
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathduplevinfo.cpp
210 lines (179 loc) · 5.46 KB
/
duplevinfo.cpp
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
//
// AYA version 5
//
// 重複回避制御を行なうクラス CDuplEvInfo
// - 主処理部
// written by umeici. 2004
//
#if defined(WIN32) || defined(_WIN32_WCE)
# include "stdafx.h"
#endif
#include <vector>
#include <functional>
#include "selecter.h"
#include "log.h"
#include "globaldef.h"
#include "sysfunc.h"
#include "ayavm.h"
//////////DEBUG/////////////////////////
#ifdef _WINDOWS
#ifdef _DEBUG
#include <crtdbg.h>
#define new new( _NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#endif
////////////////////////////////////////
/* -----------------------------------------------------------------------
* 関数名 : CDuplEvInfo::Choice
* 機能概要: 候補から選択して出力します
* -----------------------------------------------------------------------
*/
CValue CDuplEvInfo::Choice(CAyaVM &vm, size_t areanum, const std::vector<CVecValue> &values, int mode)
{
// 領域毎の候補数と総数を更新 変化があった場合は巡回順序を初期化する
if ( UpdateNums(areanum, values) ) {
lastroundorder = -1;
InitRoundOrder(vm,mode);
}
// 値の取得と巡回制御
CValue result = GetValue(vm, areanum, values);
lastroundorder = roundorder[index];
// 巡回位置を進める 巡回が完了したら巡回順序を初期化する
index++;
if ( index >= roundorder.size() ) {
InitRoundOrder(vm,mode);
}
return result;
}
size_t CDuplEvInfo::GetNum(CAyaVM &vm, size_t areanum, const std::vector<CVecValue> &values, int mode)
{
// 領域毎の候補数と総数を更新 変化があった場合は巡回順序を初期化する
if ( UpdateNums(areanum, values) ) {
lastroundorder = -1;
InitRoundOrder(vm,mode);
}
return total;
}
/* -----------------------------------------------------------------------
* 関数名 : CDuplEvInfo::InitRoundOrder
* 機能概要: 巡回順序を初期化します
* -----------------------------------------------------------------------
*/
void CDuplEvInfo::InitRoundOrder(CAyaVM &vm,int mode_param)
{
// 初期化
index = 0;
roundorder.clear();
roundorder.reserve(total);
int mode = mode_param & CHOICETYPE_SELECT_FILTER;
if ( mode == CHOICETYPE_NONOVERLAP_FLAG ) {
for(size_t i = 0; i < total; ++i) {
if ( i != lastroundorder ) {
roundorder.emplace_back(i);
}
}
//緊急時エラー回避用
if ( ! roundorder.size() ) {
roundorder.emplace_back(0);
}
//シャッフルする
size_t n = roundorder.size();
if ( n >= 2 ) {
for (size_t i = 0 ; i < n ; ++i ) {
size_t s = vm.genrand_uint(n);
if ( i != s ) {
int tmp = roundorder[i];
roundorder[i] = roundorder[s];
roundorder[s] = tmp;
}
}
}
//lastroundorderは i = 1 以降 (2個目以降) のランダムな位置に差し込む
if ( lastroundorder >= 0 ) {
if ( n >= 2 ) {
size_t lrand = vm.genrand_uint(n) + 1;
if ( lrand == n ) {
roundorder.emplace_back(lastroundorder);
}
else {
roundorder.insert(roundorder.begin() + lrand,lastroundorder);
}
}
else {
roundorder.emplace_back(lastroundorder);
}
}
}
else {
for(size_t i = 0; i < total; ++i) {
roundorder.emplace_back(i);
}
}
}
/* -----------------------------------------------------------------------
* 関数名 : CDuplEvInfo::UpdateNums
* 機能概要: 領域毎の候補数と総数を更新します
* 返値 0/1=変化なし/あり
* -----------------------------------------------------------------------
*/
bool CDuplEvInfo::UpdateNums(size_t areanum, const std::vector<CVecValue> &values)
{
// 元の候補数を保存しておく
size_t bef_numlenm1 = num.size() - 1;
// 領域毎の候補数と組み合わせ総数を更新
// 候補数に変化があった場合はフラグに記録する
bool changed = areanum != bef_numlenm1;
if ( changed ) {
num.resize(areanum+1);
}
total = 1;
for(size_t i = 0; i <= areanum; i++) {
size_t t_num = values[i].array.size();
if (num[i] != t_num) {
changed = true;
}
if(t_num)
total *= t_num;
num[i] = t_num;
}
return changed;
}
bool CDuplEvInfo::UpdateNums(const CValue& value)
{
bool changed = false;
if(num.size()!=1) {
num.resize(1);
changed = true;
}
if (num[0] != value.array().size()) {
changed = true;
total = num[0] = value.array().size();
}
return changed;
}
/* -----------------------------------------------------------------------
* 関数名 : CDuplEvInfo::GetValue
* 機能概要: 現在の巡回位置から値を取得します
*
* 格納領域が一つしかない場合はそれをそのまま出すので値の型が保護されます。
* 領域が複数ある場合はそれらは文字列として結合されますので、文字列型での出力となります。
* -----------------------------------------------------------------------
*/
CValue CDuplEvInfo::GetValue(CAyaVM &vm, size_t areanum, const std::vector<CVecValue> &values)
{
size_t t_index = roundorder[index];
vm.sysfunction().SetLso(t_index);
if (areanum) {
aya::string_t result;
for (size_t i = 0; i <= areanum; i++ ) {
if ( num[i] ) {
size_t next = t_index/num[i];
result += values[i].array[t_index - next*(num[i])].GetValueString();
t_index = next;
}
}
return CValue(result);
}
else
return values[0].array[t_index];
}