- 6737151's blog
.
- 2022-11-13 14:38:51 @
#include <bits/stdc++.h>
#include <windows.h>
#include <conio.h>
#define color(x) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),x)
#define curpos(x,y) SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),{y,x})
using namespace std;
const int MAXN = 2010;
struct RandomGenerator {
int StartSeed;
int CurSeed;
int CurCount;
RandomGenerator() {
CurCount = 0;
CurSeed = time(0);
StartSeed = CurSeed;
srand(CurSeed);
}
RandomGenerator(int Seed) {
CurCount = 0;
CurSeed = Seed;
StartSeed = CurSeed;
srand(CurSeed);
}
void Srand(int Seed) {
CurCount = 0;
CurSeed = Seed;
StartSeed = CurSeed;
srand(CurSeed);
}
int Rand() {
++CurCount;
if (CurCount==0x8000) {
CurCount = 0;
CurSeed += (StartSeed^0x66CCFF)+1;
srand(CurSeed);
}
return rand();
}
int Rand32() {
return ((Rand()>>1)<<16)|Rand()|((Rand()&1)<<15);
}
int Rand(int Mod) {
return Rand32()%Mod;
}
} Rnd;
/* nothing=0 land=1 barrier=2 fakeair=3 */
int Map[MAXN][MAXN];
/* not on route=0 on route=1 tap here=2 */
int Route[MAXN][MAXN];
/* distance to route */
int Distance[MAXN][MAXN];
/* length of default route to calculate progress */
int RouteLen = 0;
/* weight for generating random gap between tap groups */
int SleepWeight[105] = {0,0,100,0,300,0,50,0,25,0,12,0,6,0,3,0,1};
/* weight for generating random tap speed */
int TapSpeedWeight[105] = {0,0,100,0,15,0,5};
/* weight for generating random number of taps in a group */
int TapWeight[105] = {0,100,40,150,30,50,10,30,5,18,4};
/* width of path that donot contain barriers */
int Uplim=-2, Downlim=0, Leftlim=-2, Rightlim=0, Size=2000;
/* distance limit to default road to generate map features */
int DistanceLimit = 30;
/* number of tries of land spawing */
int LandSpawnTries = 5000;
/* number of tries of barrier spawing */
int BarrierSpawnTries = 40000;
/* number of default routes */
int RoadCount = 1;
/* mark if the line visited a place */
bool Way[MAXN][MAXN], Decor[MAXN][MAXN], check[MAXN][MAXN]; int px[MAXN<<1], py[MAXN<<1], pf[MAXN<<1];
/* time(ms) for each tick */
int Tick=20, ProgressMark[MAXN][MAXN];
/* size of map display at the same time */
int ScreenSize = 15;
/* air when not turn */
bool AirFlag = true;
/* seed for random generating */
int Seed = 1;
/* max time for staying in air (0 for infinite) */
int AirTimeLimit = 0;
/* use 0 for space */
string DecorChar = "00";
/* distance between checkpoints (0 for no checkpoint) */
int CheckpointDis = 300;
int DecorRate = 0;
int AirColor=11, RoadColor=10, LineColor=12, BarrierColor=6, DecorColor=11, ProgressColor=0, CheckpointColor=14;
int dx[4]={1,-1,0,0}, dy[4]={0,0,1,-1};
vector<int> Preset, vec;
void ReadSave() {
int n; scanf("%d%d",&CheckpointDis,&n);
while (n--) {
int x; scanf("%d",&x);
Preset.push_back(x); vec.push_back(x);
}
for (int i=0; i<vec.size(); ++i) {
if (i<vec.size()-i) swap(vec[i],vec[vec.size()-i]);
}
scanf("%d", &n);
for (int i=1; i<=n; ++i) scanf("%d",SleepWeight+i);
scanf("%d", &n);
for (int i=1; i<=n; ++i) scanf("%d",TapSpeedWeight+i);
scanf("%d", &n);
for (int i=1; i<=n; ++i) scanf("%d",TapWeight+i);
scanf("%d%d%d%d",&Uplim,&Downlim,&Leftlim,&Rightlim);
scanf("%d%d%d%d%d",&DistanceLimit,&LandSpawnTries,&BarrierSpawnTries,&RoadCount,&AirTimeLimit);
scanf("%d%d%d%d",&Tick,&ScreenSize,&AirFlag,&Seed); cin>>DecorChar;
for (int i=0; i<DecorChar.size(); ++i) {
if (DecorChar[i]=='0') DecorChar[i]=' ';
}
scanf("%d%d%d%d%d%d%d%d",&DecorRate,&AirColor,&RoadColor,&LineColor,&BarrierColor,&DecorColor,&ProgressColor,&CheckpointColor);
}
void WriteSave() {
printf("%d %d ",CheckpointDis,Preset.size()); for (int i=0; i<Preset.size(); ++i) printf("%d ",Preset[i]);
int mpos = 0;
for (int i=1; i<=100; ++i) {
if (SleepWeight[i]) mpos=i;
}
printf("%d ", mpos);
for (int i=1; i<=mpos; ++i) printf("%d ",SleepWeight[i]);
mpos = 0;
for (int i=1; i<=100; ++i) {
if (TapSpeedWeight[i]) mpos=i;
}
printf("%d ", mpos);
for (int i=1; i<=mpos; ++i) printf("%d ",TapSpeedWeight[i]);
mpos = 0;
for (int i=1; i<=100; ++i) {
if (TapWeight[i]) mpos=i;
}
printf("%d ", mpos);
for (int i=1; i<=mpos; ++i) printf("%d ",TapWeight[i]);
printf("%d %d %d %d ", Uplim, Downlim, Leftlim, Rightlim);
printf("%d %d %d %d %d ", DistanceLimit, LandSpawnTries, BarrierSpawnTries, RoadCount, AirTimeLimit);
printf("%d %d %d %d ", Tick, ScreenSize, AirFlag, Seed);
cout << DecorChar;
printf(" %d %d %d %d %d %d %d %d", DecorRate, AirColor, RoadColor, LineColor, BarrierColor, DecorColor, ProgressColor, CheckpointColor);
}
/* check if a position is in the map */
bool InBorder(int x, int y) {
return (((x>0)&&(y>0))&&((x<=Size)&&(y<=Size)));
}
/* mark as route to prevent barriers from spawning here */
void MarkAsRoute(int x, int y, int facing, bool Turn) {
px[RouteLen]=x; py[RouteLen]=y; pf[RouteLen]=facing;
if (!AirFlag) Turn=true;
int val=1; if (Turn) val=2;
for (int i=Uplim; i<=Downlim; ++i) {
for (int j=Leftlim; j<=Rightlim; ++j) {
if (InBorder(x+i,y+j)) {
Route[x+i][y+j] = max(Route[x+i][y+j],val);
if (Turn) Map[x+i][y+j]=1;
}
}
}
}
int GetSleepTime() {
if (vec.size()) {
int x=vec.back(); vec.pop_back(); return x;
}
int tot=0; for (int i=1; i<=50; ++i) tot+=SleepWeight[i];
/* use default value 2 if its weight array missing */
if (!tot) return 2;
int cur=0; tot=Rnd.Rand(tot);
for (int i=1; i<=50; ++i) {
cur+=SleepWeight[i]; if (cur>tot) return i;
}
return 2;
}
int GetTapCount() {
if (vec.size()) return 1;
int tot=0; for (int i=1; i<=50; ++i) tot+=TapWeight[i];
/* use default value 2 if its weight array missing */
if (!tot) return 1;
int cur=0; tot=Rnd.Rand(tot);
for (int i=1; i<=50; ++i) {
cur+=TapWeight[i]; if (cur>tot) return i;
}
return 1;
}
int GetTapSpeed() {
if (vec.size()) return 0;
int tot=0; for (int i=1; i<=50; ++i) tot+=TapSpeedWeight[i];
/* use default value 2 if its weight array missing */
if (!tot) return 2;
int cur=0; tot=Rnd.Rand(tot);
for (int i=1; i<=50; ++i) {
cur+=TapSpeedWeight[i]; if (cur>tot) return i;
}
return 2;
}
void GenerateRoute() {
int x=10, y=1, facing=0; RouteLen=0;
/* safe path at the beginning */
for (int i=1; i<=10; ++i) {
++RouteLen; MarkAsRoute(i,1,0,true);
}
while (InBorder(x,y)) {
/* generate a group of taps */
int TapSpeed=GetTapSpeed(), TapCount=GetTapCount();
while (TapCount--) {
/* turn here */
MarkAsRoute(x,y,facing^1,true); facing^=1;
for (int i=0; i<TapSpeed; ++i) {
if (facing) ++y;
else ++x;
if (!InBorder(x,y)) return;
++RouteLen; MarkAsRoute(x,y,facing,false);
}
}
/* sleep between group of taps */
int SleepTime = GetSleepTime();
while (SleepTime--) {
if (facing) ++y;
else ++x;
if (!InBorder(x,y)) return;
++RouteLen; MarkAsRoute(x,y,facing,false);
}
}
}
/* calculate distance to default path */
void CalcDistance() {
DistanceLimit += 2;
queue<int> qx, qy;
if (CheckpointDis) {
for (int i=CheckpointDis; ((i<=RouteLen)&&(px[i])); i+=CheckpointDis) check[px[i]][py[i]]=true;
}
for (int i=1; i<=Size; ++i) {
for (int j=1; j<=Size; ++j) {
if (Route[i][j]) {
Distance[i][j]=1; qx.push(i); qy.push(j);
}
}
}
while (!qx.empty()) {
int x=qx.front(), y=qy.front();
qx.pop(); qy.pop();
for (int i=0; i<4; ++i) {
int nx=x+dx[i], ny=y+dy[i];
if ((!InBorder(nx,ny))||(Distance[nx][ny])) continue;
Distance[nx][ny] = Distance[x][y]+1;
qx.push(nx); qy.push(ny);
}
}
}
/* generate random barriers */
void SetBarrier() {
for (int cc=0; cc<BarrierSpawnTries; ++cc) {
int sx=Rnd.Rand(3)+2, sy=Rnd.Rand(3)+2;
int x=Rnd.Rand(Size-sx+1)+1, y=Rnd.Rand(Size-sy+1)+1;
int Attempt = 0;
while (Distance[x][y]>DistanceLimit) {
x=Rnd.Rand(Size-sx+1)+1; y=Rnd.Rand(Size-sy+1)+1;
if (++Attempt>200) break;
}
if (Attempt>200) continue;
bool RouteCorrect = true;
for (int i=0; i<sx; ++i) {
for (int j=0; j<sy; ++j) {
if (Route[x+i][y+j]) {
RouteCorrect=false; break;
}
}
if (!RouteCorrect) break;
}
if (!RouteCorrect) continue;
for (int i=0; i<sx; ++i) {
for (int j=0; j<sy; ++j) Map[x+i][y+j]=2;
}
}
}
/* generate land blocks */
void SetLand() {
for (int cc=0; cc<LandSpawnTries; ++cc) {
int sx=Rnd.Rand(11)+2, sy=Rnd.Rand(11)+2;
int x=Rnd.Rand(Size-sx+1)+1, y=Rnd.Rand(Size-sy+1)+1;
int Attempt = 0;
while (Distance[x][y]>DistanceLimit) {
x=Rnd.Rand(Size-sx+1)+1; y=Rnd.Rand(Size-sy+1)+1;
if (++Attempt>200) break;
}
if (Attempt>200) continue;
for (int i=0; i<sx; ++i) {
for (int j=0; j<sy; ++j) {
if (!Map[x+i][y+j]) Map[x+i][y+j]=1;
}
}
}
}
/* set border */
void SetBorder() {
for (int i=100; i<=RouteLen; i+=100) {
int x=Rnd.Rand(Size)+1, y=i-x, cc=0;
for (;;) {
if ((InBorder(x,y))&&(Distance[x][y]<=10)&&(Map[x][y]==Map[x][y+1])) break;
x=Rnd.Rand(Size)+1; y=i-x;
if (++cc==1000) break;
}
if (cc<1000) {
ProgressMark[x][y+1]=i/100; ProgressMark[x][y]=-1;
}
}
for (int i=1; i<=Size; ++i) {
for (int j=1; j<=Size; ++j) {
if ((Rnd.Rand(100)<DecorRate)&&(!Map[i][j])) Decor[i][j]=true;
if ((!Map[i][j])&&(Distance[i][j]>DistanceLimit)) Map[i][j]=3;
}
}
}
void PrintMap(int x, int y) {
for (int i=-ScreenSize; i<=ScreenSize; ++i) {
for (int j=-ScreenSize; j<=ScreenSize; ++j) {
int clr = 0;
if ((!i)&&(!j)) clr=LineColor;
else if ((!InBorder(x+i,y+j))||((!check[x+i][y+j])&&((Map[x+i][y+j]==3)||(!Map[x+i][y+j])))) clr=AirColor;
else if (Way[x+i][y+j]) clr=LineColor;
else if ((check[x+i][y+j])&&(i+j>0)) clr=CheckpointColor;
else if (Map[x+i][y+j]==1) clr=RoadColor;
else if (Map[x+i][y+j]==2) clr=BarrierColor;
curpos(ScreenSize-i, (ScreenSize-j)<<1);
color(clr*16+DecorColor);
if (((x)||(y))&&(InBorder(x+i,y+j))&&(!Way[x+i][y+j])&&(!check[x+i][y+j])&&(ProgressMark[x+i][y+j])) {
color(clr*16+ProgressColor);
if (ProgressMark[x+i][y+j]>0) printf("%2d",ProgressMark[x+i][y+j]);
else printf("00");
}
else if ((InBorder(x+i,y+j))&&(Decor[x+i][y+j])) cout<<DecorChar;
else printf(" ");
}
color(0); curpos(ScreenSize-i,(ScreenSize<<2)+2); printf(" ");
}
}
int mss=0, sx=1, sy=1, sf=0, slen=0, nxtpoint=CheckpointDis;
void doit() {
memset(Way, false, sizeof(Way));
int x=sx, y=sy, facing=sf, len=slen, AirTime=0; Way[x][y]=true;
system("cls");
PrintMap(x,y); getch();
for (;;) {
if (facing) ++y;
else ++x;
++len;
if (CheckpointDis) {
if (len==nxtpoint) {
if (px[len]) {
sx=px[len]; sy=py[len]; sf=pf[len]; slen=len;
}
nxtpoint += CheckpointDis;
}
}
if (Map[x][y]==1) Way[x][y]=true;
PrintMap(x, y);
if ((!InBorder(x,y))||(Map[x][y]>1)) {
curpos(ScreenSize<<1|1,0); color(15);
mss = max(mss,len);
if (!InBorder(x,y)) printf("state completed.\n");
else printf("quitted. [crash]\n");
printf("score=%d record=%d",len,mss); getch();
return;
}
if (!Map[x][y]) ++AirTime;
else AirTime=0;
if ((AirTimeLimit)&&(AirTime>AirTimeLimit)) {
curpos(ScreenSize<<1|1,0); color(15);
printf("quitted. [fall]\n"); mss=max(mss,len);
printf("score=%d record=%d",len,mss); getch();
return;
}
if (kbhit()) {
char ch = getch();
if ((ch=='R')||(ch=='r')) {
curpos(ScreenSize<<1|1,0); color(15);
mss = max(mss,len);
if (!InBorder(x,y)) printf("state completed.\n");
else printf("quitted. [reset]\n");
printf("score=%d record=%d",len,mss); getch();
return;
}
if (Map[x][y]==1) facing^=1;
}
Sleep(Tick);
}
}
int main() {
printf("default(0) or read(1) save?\n");
char x = getch();
while ((x!='0')&&(x!='1')) x=getch();
if (x=='0') {
WriteSave();
printf("\nis current save.\n");
}
else {
printf("Input Save : "); ReadSave();
}
Rnd.Srand(Seed);
for (int i=0; i<RoadCount; ++i) GenerateRoute();
CalcDistance();
SetBarrier();
SetLand();
SetBorder();
while (kbhit()) getch();
printf("load completed. press any key to start\n");
getch();
for (;;) doit();
return 0;
}
Preset
0 46 15 12 3 3 18 6 6 6 18 9 3 6 6 12 6 6 6 18 12 3 3 12 3 3 6 6 6 6 6 3 3 6 6 6 3 3 6 6 6 3 3 6 6 6 6 30 16 0 100 0 300 0 50 0 25 0 12 0 6 0 3 0 1 6 0 100 0 15 0 5 10 100 40 150 30 50 10 30 5 18 4 0 0 0 0 30 0 1000 1 3 0 15 0 1 0* 4 11 8 2 7 10 0 14