Initial (manual) import

This commit is contained in:
minexew committed 2017-01-22 20:26:44 +01:00
1 parent f39611c506
commit 895fe109de
661 files changed
+245862

No files matched your search

+166
View File
@@ -0,0 +1,166 @@
U0 PlayerIndirect()
{
Unit *tmpu=NULL;
I64 i,remaining=0,msg_code,arg1,arg2;
F64 target_x,target_y;
ViewPlayerSet(cur_player);
for (i=0;i<UNITS_NUM;i++) {
tmpu=&units[cur_player][i];
if (tmpu->life>0 && tmpu->indirect_fire)
remaining++;
}
while (remaining) {
if (!alive_cnt[0] || !alive_cnt[1])
throw('GameOver',TRUE);
msg_code=GetMsg(&arg1,&arg2,1<<MSG_KEY_DOWN|1<<MSG_MS_L_DOWN|1<<MSG_MS_L_UP|
1<<MSG_MS_R_UP);
switch (msg_code) {
case MSG_KEY_DOWN:
CharDo(arg1);
break;
case MSG_MS_L_DOWN:
if (CursorInWin(Fs,arg1,arg2)) {
arg1-=x0; arg2-=y0;
CursorUpdate(Fs,arg1,arg2);
if (tmpu=UnitFind(cursor_row,cursor_col)) {
if (tmpu->player==enemy_player || tmpu->fired ||
!tmpu->indirect_fire)
tmpu=NULL;
else {
RowCol2XY(&fire_radius_x,&fire_radius_y,tmpu->row,tmpu->col);
fire_radius=tmpu->range*2*HEX_RADIUS;
}
}
}
break;
case MSG_MS_L_UP:
if (CursorInWin(Fs,arg1,arg2)) {
arg1-=x0; arg2-=y0;
CursorUpdate(Fs,arg1,arg2);
RowCol2XY(&target_x,&target_y,cursor_row,cursor_col);
if (!tmpu)
Beep;
else {
if (Sqrt(Sqr(fire_radius_x-target_x)+Sqr(fire_radius_y-target_y))>
fire_radius)
Beep;
else {
IndirectAdd(tmpu,cursor_row,cursor_col);
remaining--;
}
}
}
tmpu=NULL;
fire_radius=0;
break;
case MSG_MS_R_UP:
if (CursorInWin(Fs,arg1,arg2))
throw('PhaseOvr',TRUE);
break;
}
}
throw('PhaseOvr',TRUE);
}
U0 PlayerMove()
{
Unit *tmpu=NULL;
I64 msg_code,arg1,arg2;
ViewPlayerSet(cur_player);
while (TRUE) {
if (!alive_cnt[0] || !alive_cnt[1])
throw('GameOver',TRUE);
msg_code=GetMsg(&arg1,&arg2,1<<MSG_KEY_DOWN|1<<MSG_MS_L_DOWN|1<<MSG_MS_L_UP|
1<<MSG_MS_R_UP);
switch (msg_code) {
case MSG_KEY_DOWN:
CharDo(arg1);
break;
case MSG_MS_L_DOWN:
if (CursorInWin(Fs,arg1,arg2)) {
arg1-=x0; arg2-=y0;
CursorUpdate(Fs,arg1,arg2);
if (tmpu=UnitFind(cursor_row,cursor_col)) {
if (tmpu->player==enemy_player || !tmpu->remaining_movement)
tmpu=NULL;
}
}
break;
case MSG_MS_L_UP:
if (CursorInWin(Fs,arg1,arg2)) {
arg1-=x0; arg2-=y0;
CursorUpdate(Fs,arg1,arg2);
if (!tmpu)
Beep;
else {
UnitMove(tmpu,arg1,arg2);
break;
}
}
tmpu=NULL;
break;
case MSG_MS_R_UP:
if (CursorInWin(Fs,arg1,arg2))
throw('PhaseOvr',TRUE);
break;
}
}
}
U0 PlayerDirect()
{
Unit *tmpu=NULL,*target;
I64 msg_code,arg1,arg2;
ViewPlayerSet(cur_player);
while (TRUE) {
if (!alive_cnt[0] || !alive_cnt[1])
throw('GameOver',TRUE);
msg_code=GetMsg(&arg1,&arg2,1<<MSG_KEY_DOWN|1<<MSG_MS_L_DOWN|1<<MSG_MS_L_UP|
1<<MSG_MS_R_UP);
switch (msg_code) {
case MSG_KEY_DOWN:
CharDo(arg1);
break;
case MSG_MS_L_DOWN:
if (CursorInWin(Fs,arg1,arg2)) {
arg1-=x0; arg2-=y0;
CursorUpdate(Fs,arg1,arg2);
if (tmpu=UnitFind(cursor_row,cursor_col)) {
if (tmpu->player==enemy_player || tmpu->fired ||
tmpu->indirect_fire)
tmpu=NULL;
else {
VRSetUp(cur_player);
RowCol2XY(&fire_radius_x,&fire_radius_y,tmpu->row,tmpu->col);
fire_radius=tmpu->range*2*HEX_RADIUS;
VisRecalc(VR_ONE_FRIENDLY_UNIT,tmpu);
}
}
}
break;
case MSG_MS_L_UP:
if (CursorInWin(Fs,arg1,arg2)) {
arg1-=x0; arg2-=y0;
CursorUpdate(Fs,arg1,arg2);
target=UnitFind(cursor_row,cursor_col);
if (!tmpu)
Beep;
else {
if (!target || target->player!=enemy_player ||
!Bt(&target->vis,0))
Beep;
else
UnitDirectFire(tmpu,target);
VisRecalc(VR_UPDATE_FRIENDLY_UNIT,tmpu);
}
}
tmpu=NULL;
fire_radius=0;
break;
case MSG_MS_R_UP:
if (CursorInWin(Fs,arg1,arg2))
throw('PhaseOvr',TRUE);
break;
}
}
}
@@ -0,0 +1,79 @@
Unit *UnitNearestFind(I64 row,I64 col,I64 player,Bool in_LOS,F64 range=-1)
{
I64 i;
F64 dd,best_dd=F64_MAX,x1,y1,x2,y2;
Unit *best=NULL;
//$LK,"Sqrt",A="MN:Sqrt"$() is slow, so work with squared distances.
if (range<0)
range=F64_MAX;
else
range*=range;
RowCol2XY(&x1,&y1,row,col);
for (i=0;i<UNITS_NUM;i++)
if (units[player][i].life>0) {
if (!in_LOS || LOS(row,col,units[player][i].row,units[player][i].col)) {
RowCol2XY(&x2,&y2,units[player][i].row,units[player][i].col);
dd=Sqr(x2-x1)+Sqr(y2-y1);
if (dd<=range && dd<best_dd) {
best=&units[player][i];
best_dd=dd;
}
}
}
return best;
}
U0 PlayerIndirect()
{
Unit *target,*tmpu;
I64 i;
for (i=0;i<UNITS_NUM;i++) {
UserChk;
tmpu=&units[cur_player][i];
if (tmpu->life>0 && tmpu->indirect_fire &&
(target=UnitNearestFind(tmpu->row,tmpu->col,enemy_player,TRUE,
tmpu->range*2*HEX_RADIUS)))
IndirectAdd(tmpu,target->row,target->col);
}
throw('PhaseOvr',TRUE);
}
U0 PlayerMove()
{
Unit *target,*tmpu;
I64 i;
F64 x,y;
for (i=0;i<UNITS_NUM;i++) {
UserChk;
tmpu=&units[cur_player][i];
if (tmpu->life>0) {
//Cheats because it violates Line-of-Sight
if (target=UnitNearestFind(tmpu->row,tmpu->col,enemy_player,FALSE)) {
RowCol2XY(&x,&y,target->row,target->col);
if (!UnitMove(tmpu,x,y)) {
RowCol2XY(&x,&y,tmpu->row,tmpu->col);
UnitMove(tmpu,x+RandI16,y+RandI16);
}
}
}
}
throw('PhaseOvr',TRUE);
}
U0 PlayerDirect()
{
Unit *target,*tmpu;
I64 i;
for (i=0;i<UNITS_NUM;i++) {
UserChk;
tmpu=&units[cur_player][i];
if (tmpu->life>0 && !tmpu->indirect_fire &&
(target=UnitNearestFind(tmpu->row,tmpu->col,enemy_player,TRUE,
tmpu->range*2*HEX_RADIUS))) {
UnitDirectFire(tmpu,target);
Sleep(250*animation_delay);
}
}
throw('PhaseOvr',TRUE);
}
+2
View File
@@ -0,0 +1,2 @@
MkDir("~/ToTheFront");
+13
View File
@@ -0,0 +1,13 @@
#help_index "Games"
Cd(__DIR__);;
#include "TTFGlbls"
#include "TTFLib"
#include "TTFInit"
#include "TTFVis"
#include "TTFFire"
#include "TTFMove"
#include "TTFDraw"
#include "ToTheFront"
#help_index ""
+3
View File
@@ -0,0 +1,3 @@
Cd(__DIR__);;
#include "Load"
ToTheFront;
Binary file not shown.
+278
View File
@@ -0,0 +1,278 @@
U0 AttackHeader(Unit *tmpu,U8 *st,Unit *target)
{
I64 i=9+StrLen(st);
if (target) {
i+=9;
if (target->armor)
i+=8;
else
i+=10;
}
'\n\n';
"$$BLACK$$%h*c$$FG$$\n",i,'-';
if (tmpu->player)
"$$PURPLE$$Player 2$$FG$$ ";
else
"$$CYAN$$Player 1$$FG$$ ";
"%s",st;
if (target) {
if (target->player)
" $$PURPLE$$Player 2";
else
" $$CYAN$$Player 1";
if (target->armor)
" Armored";
else
" Unarmored";
'$$FG$$';
}
'\n';
"$$BLACK$$%h*c$$FG$$\n",i,'-';
}
F64 HitDamage(Unit *tmpu,Unit *target,I64 facing=1,F64 range_factor=0)
{
F64 d,res=200.0*Rand;
"\nRoll Out of 200\t\t:%6.2f Damage\n",res;
if (target->armor) {
d=target->armor/100.0*(5-facing)/5.0;
if (d>=0) {
"Armor Attack\t\t:%6.2f\n",ToF64(tmpu->armored_attack);
res*=(tmpu->armored_attack/100.0)/d;
} else
res=0;
"Armor(%z) Defense\t:%6.2f\n",facing,
"Front\0FrontSide\0RearSide\0Rear\0",100*d;
} else {
d=1.0-range_factor;
if (d>0) {
"Unarmored Attack\t:%6.2f\n",ToF64(tmpu->unarmored_attack);
"Range Adjust\t\t:%6.2f%%\n",100*d;
res*=(tmpu->unarmored_attack/100.0)*d;
} else
res=0;
}
"Attack/Defense Adjusted\t:%6.2f Damage\n",res;
return Round(res);
}
Bool DamageDo(Unit *target,F64 damage)
{
if (damage>0) {
if (target->armor)
"Armor Hit Score %6.2f\t:",damage;
else
"%3d Life - %3f Damage\t=",target->life,damage;
if (damage>=target->life) {
"$$RED$$Killed$$FG$$\n";
Noise(1000*animation_delay,74,98);
Sleep(1000*animation_delay);
target->life=0;
VisRecalc(VR_FRIENDLY_UNIT_DIED,target);
alive_cnt[target->player]--;
return TRUE;
} else {
if (target->armor) {
if (damage>0.6*target->life) {
target->movement=0;
"$$RED$$Immobilized$$FG$$\n";
} else
"$$GREEN$$No Penetration$$FG$$\n";
} else {
target->life-=damage;
"$$RED$$%6.2f Life$$FG$$\n",ToF64(target->life);
}
return FALSE;
}
} else
return FALSE;
}
U0 IndirectAdd(Unit *tmpu,I64 row,I64 col)
{
IndirectOrders *tmpi;
if (tmpu->life<=0 || tmpu->range<=0)
return;
tmpu->fired=TRUE;
tmpi=CAlloc(sizeof(IndirectOrders));
tmpi->attacker=tmpu;
tmpi->row=row;
tmpi->col=col;
QueIns(tmpi,indirect_head.last);
}
Bool BulletPlot(U0,I64 x,I64 y,I64)
{
fire_x=x; fire_y=y;
firing=TRUE;
Sleep(3*animation_delay);
return TRUE;
}
U0 UnitDirectFire(Unit *tmpu,Unit *target)
{
I64 r,c,facing,
t1=terrain[tmpu->row][tmpu->col],t2=terrain[target->row][target->col];
F64 x1,y1,x2,y2,d,a,range_factor;
if (tmpu->life<=0 || target->life<=0 || tmpu->range<=0)
return;
AttackHeader(tmpu,"DirectFire",target);
RowCol2XY(&x1,&y1,tmpu->row,tmpu->col);
RowCol2XY(&x2,&y2,target->row,target->col);
d=100*Rand;
"+%5.2f Roll\n",d;
d+=tmpu->accuracy;
"+%2d.00 Accuracy\n",tmpu->accuracy;
range_factor=Sqrt(Sqr(x2-x1)+Sqr(y2-y1))/(tmpu->range*2*DSIN);
"-%5.2f%% of Range\n",100*range_factor;
d-=100*range_factor;
if (t2==TREES) {
"-30.00 Target in Trees Penalty\n";
d-=30;
}
if (t1==MOUNTAINS && t2!=MOUNTAINS) {
"+30.00 High Ground Bonus\n";
d+=30;
}
"_______\n";
target_unit=target;
if (d>=0) {
"+%5.2f Hit\n",d;
target_hit=TRUE;
Noise(500*animation_delay,34,41);
Sleep(500*animation_delay);
Line(NULL,x1,y1,0,x2,y2,0,&BulletPlot);
} else {
"-%5.2f Miss\n",-d;
target_hit=FALSE;
Noise(1000*animation_delay,69,74);
Sleep(1000*animation_delay);
a=ã*2*Rand;
d=(0.5-d/100)*HEX_SIDE;
Line(NULL,x1,y1,0,x2+d*Cos(a),y2+d*Sin(a),0,&BulletPlot);
}
firing=FALSE;
tmpu->fired=TRUE;
if (target_hit) {
r=target->row;c=target->col;
if ((facing=HexMoveOne(&r,&c,x1,y1))>=0)
facing=FacingChg(facing,target->facing);
else
facing=0;
DamageDo(target,HitDamage(tmpu,target,facing,range_factor));
}
while (snd.ona!=ONA_REST) //see $LK,"Snd",A="MN:Snd"$()
Yield;
target_unit=NULL;
}
Bool HexOccupy(Bool overrun,Unit *tmpu,Unit *target)
{
I64 t2=terrain[target->row][target->col];
F64 damage;
if (tmpu->life<=0 || target->life<=0)
return FALSE;
if (overrun)
AttackHeader(tmpu,"OverRun",target);
else
AttackHeader(tmpu,"CloseAssault",target);
Noise(500*animation_delay,34,41);
Sleep(500*animation_delay);
tmpu->fired=TRUE;
target->fired=TRUE;
damage=HitDamage(tmpu,target);
if (overrun) {
damage*=2.0;
"x2 OverRun Bonus\t=%6.2f Damage\n",damage;
if (t2!=PLAINS) {
damage/=2.0;
"/2 Terrain Penalty\t=%6.2f Damage\n",damage;
}
} else {
damage*=3.0;
"x3 CloseAssault Bonus\t=%6.2f Damage\n",damage;
}
if (DamageDo(target,Round(damage))) {
"$$RED$$Success$$FG$$\n";
while (snd.ona!=ONA_REST) //see $LK,"Snd",A="MN:Snd"$()
Yield;
return TRUE;
} else {
tmpu->life=0;
VisRecalc(VR_FRIENDLY_UNIT_DIED,tmpu);
alive_cnt[tmpu->player]--;
"$$RED$$Failure$$FG$$\n";
while (snd.ona!=ONA_REST) //see $LK,"Snd",A="MN:Snd"$()
Yield;
return FALSE;
}
}
U0 IndirectResolveAll()
{
I64 i,r,c;
F64 x1,y1,x2,y2,d,range_factor;
Unit *tmpu,*target;
IndirectOrders *tmpi=indirect_head.next,*tmpi1;
while (tmpi!=*indirect_head) {
tmpi1=tmpi->next;
tmpu=tmpi->attacker;
AttackHeader(tmpu,"IndirectFire",NULL);
RowCol2XY(&x1,&y1,tmpu->row,tmpu->col);
RowCol2XY(&x2,&y2,tmpi->row,tmpi->col);
d=100*Rand;
"+%5.2f Roll\n",d;
d+=tmpu->accuracy;
"+%2d.00 Accuracy\n",tmpu->accuracy;
range_factor=Sqrt(Sqr(x2-x1)+Sqr(y2-y1))/(tmpu->range*2*DSIN);
"-%5.2f%% of Range\n",100*range_factor;
d-=100*range_factor;
'_______\n';
if (d>=0) {
"+%5.2f Hit\n",d;
Noise(500*animation_delay,34,41);
Sleep(500*animation_delay);
} else {
"-%5.2f Miss\n",-d;
Noise(1000*animation_delay,69,74);
Sleep(1000*animation_delay);
i=RandU16%6;
if (tmpi->row&1)
tmpi->col+=col_offsets_odd[i];
else
tmpi->col+=col_offsets_even[i];
tmpi->row+=row_offsets[i];
RowCol2XY(&x2,&y2,tmpi->row,tmpi->col);
}
Line(NULL,x1,y1,0,x2,y2,0,&BulletPlot);
firing=FALSE;
tmpu->fired=TRUE;
indirect_row=tmpi->row;
indirect_col=tmpi->col;
indirect_explosion=TRUE;
for (i=0;i<7;i++) {
if (tmpi->row&1)
c=tmpi->col+col_offsets_odd[i];
else
c=tmpi->col+col_offsets_even[i];
r=tmpi->row+row_offsets[i];
if (0<=r<map_rows && 0<=c<map_cols && (target=UnitFind(r,c))) {
AttackHeader(tmpu,"IndirectFire",target);
DamageDo(target,HitDamage(tmpu,target));
}
}
Noise(2000*animation_delay,70,74);
Sleep(2000*animation_delay);
while (snd.ona!=ONA_REST) //see $LK,"Snd",A="MN:Snd"$()
Yield;
indirect_explosion=FALSE;
QueRem(tmpi);
Free(tmpi);
tmpi=tmpi1;
}
}
+108
View File
@@ -0,0 +1,108 @@
#define MAP_WIDTH 640 //Change this, if you like.
#define UNITS_NUM 32 //Change this, if you like.
#define HEX_SIDE 11
U0 InitDefines()
{
DefinePrint("MAP_HEIGHT","%d",(GR_HEIGHT-FONT_HEIGHT*2)*MAP_WIDTH/GR_WIDTH);
DefinePrint("DCOS", "%12.9f", HEX_SIDE*Cos(60.0/180*ã));
DefinePrint("DSIN", "%12.9f", HEX_SIDE*Sin(60.0/180*ã));
DefinePrint("HEX_RADIUS","%12.9f", HEX_SIDE*Sin(60.0/180*ã)+0.01); //Slop
} InitDefines;
I64 map_cols=(MAP_WIDTH-DCOS)/(2*HEX_SIDE+2*DCOS),
map_rows=ToI64((MAP_HEIGHT-DSIN)/DSIN)&~1,
map_width=map_cols*(2*HEX_SIDE+2*DCOS)+DCOS,
map_height=map_rows*DSIN+DSIN+1,
x0,y0;
CDC *map_dc;
U8 terrain[map_rows][map_cols];
//Centers of hexes
class Pt
{
F64 x,y;
};
Pt hex_centers[map_rows][map_cols];
I64 show_vis_row,show_vis_col;
Bool roads[map_rows][map_cols],
rivers[map_rows][map_cols],
vis_map[map_rows][map_cols];
//Other options for PLAINS are WHITE or YELLOW
#define PLAINS LTGREEN
#define TREES GREEN
#define MOUNTAINS DKGRAY
//These are used to display a range circle when they player
//is firing.
F64 fire_radius,fire_radius_x,fire_radius_y;
//These display "phase", "turn" and "game over".
U8 msg_buf[STR_LEN];
I64 msg_off_timeout; //Jiffies. Goes away after a time.
//Unit types
#define UT_INFANTRY 0
#define UT_ARTILLERY 1
#define UT_LT_TANK 2
#define UT_MD_TANK 3
class Unit
{
U8 *img;
I64 num,row,col,
armored_attack,unarmored_attack,armor;
I8 type,player,facing,movement,life,
range,remaining_movement,accuracy;
Bool vis[2],fired,infantry,indirect_fire,pad[3];
};
Unit units[2][UNITS_NUM];
// Bt(vis_unit_bitmap,player1+player0*((UNITS_NUM+7)&~7))
U8 vis_unit_bitmap[2][(((UNITS_NUM+7)&~7)*UNITS_NUM)>>3];
#define PHASE_START 0
#define PHASE_INDIRECT 0
#define PHASE_INDIRECT0 0
#define PHASE_INDIRECT1 1
#define PHASE_MOVE 2
#define PHASE_MOVE0 2
#define PHASE_MOVE1 3
#define PHASE_DIRECT 4
#define PHASE_DIRECT0 4
#define PHASE_DIRECT1 5
#define PHASE_END 6
I64 phase,cur_player,enemy_player,view_player,turn,
cursor_row,cursor_col,alive_cnt[2],
player_indirect[2],player_move[2],player_direct[2];
F64 animation_delay=0.5;
Bool moving=FALSE;
I64 move_x,move_y;
F64 move_facing;
Unit *moving_unit;
extern I64 HexMoveOne(I64 *_row,I64 *_col,F64 x,F64 y);
class IndirectOrders
{
IndirectOrders *next,*last;
Unit *attacker;
I64 row,col;
} indirect_head;
Bool firing=FALSE;
I64 fire_x,fire_y;
Unit *target_unit;
Bool target_hit;
Bool indirect_explosion=FALSE;
I64 indirect_row,indirect_col;
I64 row_offsets[7]={-1,-2,-1,1,2,1,0};
I64 col_offsets_even[7]={-1, 0, 0,0,0,-1,0};
I64 col_offsets_odd [7]={ 0, 0, 1,1,0, 0,0};
+436
View File
@@ -0,0 +1,436 @@
/*I got tricky by not defining a color
right away in these $LK,"CSprite",A="MN:CSprite"$s so they can
work for both players by setting dc->color
before drawing them. I actually made these
graphics by defining a color in the <CTRL-r>
menu, drawing the unit and deleting the color.
I had to leave a gap between the tank tread
and body because of how it is rendered when rotated.
*/
$SP,"<1>",BI=1$
$SP,"<2>",BI=2$
//This is an infantry.
$SP,"<3>",BI=3$
$SP,"<4>",BI=4$
U0 DrawHexes()
{
F64 dx=2*HEX_SIDE+2*DCOS,dy=2*DSIN,
x,y,x1,y1,x2,y2;
I64 i,j;
map_dc->color=WHITE;
GrRect(map_dc,0,0,map_dc->width,map_dc->height);
map_dc->color=BLACK;
y=0;
for (j=0;j<map_rows;j+=2) {
x=DCOS;
GrLine(map_dc,x,y,x-DCOS,y+DSIN);
GrLine(map_dc,x-DCOS,y+DSIN,x,y+2*DSIN);
for (i=0;i<map_cols;i++) {
x1=x; y1=y;
x2=x1+HEX_SIDE; y2=y1;
GrLine(map_dc,x1,y1,x2,y2);
x1=x2; y1=y2;
x2+=DCOS; y2+=DSIN;
GrLine(map_dc,x1,y1,x2,y2);
GrLine(map_dc,x2,y2,x2-DCOS,y2+DSIN);
x1=x2; y1=y2;
x2+=HEX_SIDE;
GrLine(map_dc,x1,y1,x2,y2);
GrLine(map_dc,x2,y2,x2+DCOS,y2+DSIN);
x1=x2; y1=y2;
x2+=DCOS; y2-=DSIN;
if (j || i<map_cols-1)
GrLine(map_dc,x1,y1,x2,y2);
x+=dx;
}
y+=dy;
}
x=DCOS;
for (i=0;i<map_cols;i++) {
x1=x; y1=y;
x2=x1+HEX_SIDE; y2=y1;
GrLine(map_dc,x1,y1,x2,y2);
x1=x2; y1=y2;
x2+=DCOS; y2+=DSIN;
GrLine(map_dc,x1,y1,x2,y2);
x1=x2; y1=y2;
x2+=HEX_SIDE;
GrLine(map_dc,x1,y1,x2,y2);
x1=x2; y1=y2;
x2+=DCOS; y2-=DSIN;
GrLine(map_dc,x1,y1,x2,y2);
x+=dx;
}
}
U0 MakeTerrain(U8 color,I64 cnt,I64 cluster_lo,I64 cluster_hi)
{
I64 i,j,l,row,col;
for (i=0;i<cnt;i++) {
col=RandU32%map_cols;
row=RandU32%map_rows;
l=cluster_lo+RandU16%(cluster_hi-cluster_lo+1);
for (j=0;j<l;j++) {
terrain[row][col]=color;
Toward(&row,&col,RandU16%6);
col=ClampI64(col,0,map_cols-1);
row=ClampI64(row,0,map_rows-1);
}
}
}
U0 MakeRivers()
{
I64 i,row,col,direction;
for (i=0;i<4;i++) {
row=RandU32%map_rows;
col=RandU32%map_cols;
direction=RandU16%6;
while (TRUE) {
rivers[row][col]=TRUE;
Toward(&row,&col,direction);
if (!(0<=row<map_rows && 0<=col<map_cols))
break;
if (!(RandU16&3))
direction=(direction+(7-RandU16%3))%6;
}
}
}
U0 MakeRoads()
{
I64 i,row,col,direction;
for (i=0;i<5;i++) {
row=RandU32%map_rows;
col=RandU32%map_cols;
direction=RandU16%6;
while (TRUE) {
roads[row][col]=TRUE;
Toward(&row,&col,direction);
if (!(0<=row<map_rows && 0<=col<map_cols))
break;
if (!(RandU16%3))
direction=(direction+(7-RandU16%3))%6;
}
}
}
U0 DrawTerrain()
{
I64 i,j;
F64 x,y;
for (j=0;j<map_rows;j++)
for (i=0;i<map_cols;i++) {
map_dc->color=terrain[j][i];
RowCol2XY(&x,&y,j,i);
GrFloodFill(map_dc,x,y);
}
}
U0 DrawRivers()
{
I64 i,j,k,r,c;
F64 x1,y1,x2,y2;
for (j=0;j<map_rows;j++)
for (i=0;i<map_cols;i++) {
if (rivers[j][i]) {
RowCol2XY(&x1,&y1,j,i);
for (k=0;k<6;k++) {
r=j;c=i;
Toward(&r,&c,k);
if (0<=r<map_rows && 0<=c<map_cols &&
rivers[r][c]) {
RowCol2XY(&x2,&y2,r,c);
map_dc->color=LTBLUE;
map_dc->pen_width=4;
GrLine3(map_dc,x1,y1,0,x2,y2,0);
map_dc->color=BLUE;
map_dc->pen_width=2;
GrLine3(map_dc,x1,y1,0,x2,y2,0);
}
}
}
}
}
U0 DrawRoads()
{
I64 i,j,k,r,c;
F64 x1,y1,x2,y2;
map_dc->color=RED;
map_dc->pen_width=3;
for (j=0;j<map_rows;j++)
for (i=0;i<map_cols;i++) {
if (roads[j][i]) {
RowCol2XY(&x1,&y1,j,i);
for (k=0;k<6;k++) {
r=j;c=i;
Toward(&r,&c,k);
if (0<=r<map_rows && 0<=c<map_cols &&
roads[r][c]) {
RowCol2XY(&x2,&y2,r,c);
GrLine3(map_dc,x1,y1,0,x2,y2,0);
}
}
}
}
}
U0 DrawDots()
{
I64 i,j;
F64 x,y;
map_dc->color=BLACK;
for (j=0;j<map_rows;j++)
for (i=0;i<map_cols;i++) {
RowCol2XY(&x,&y,j,i);
GrPlot(map_dc,x,y);
}
}
U0 HexCentersCalc()
{
I64 i,j;
F64 x,y;
for (j=0;j<map_rows;j++)
for (i=0;i<map_cols;i++) {
x=(2*HEX_SIDE+2*DCOS)*i+HEX_SIDE/2+DCOS;
if (j&1)
x+=HEX_SIDE+DCOS;
y=DSIN*(j+1);
hex_centers[j][i].x=x;
hex_centers[j][i].y=y;
}
}
U0 InitMap()
{
HexCentersCalc;
DrawHexes;
MemSet(terrain,PLAINS,sizeof(terrain));
MemSet(roads,FALSE,sizeof(roads));
MemSet(rivers,FALSE,sizeof(rivers));
MemSet(vis_map,FALSE,sizeof(vis_map));
MakeTerrain(MOUNTAINS,0.03*map_cols*map_cols,5,35);
MakeTerrain(TREES,0.03*map_cols*map_cols,5,35);
DrawTerrain;
MakeRivers;
DrawRivers;
MakeRoads;
DrawRoads;
DrawDots;
}
U0 InitUnits()
{
I64 i,j,row,col,type;
Unit *tmpu;
MemSet(units,0,sizeof(units));
alive_cnt[0]=alive_cnt[1]=UNITS_NUM;
for (j=0;j<2;j++)
for (i=0;i<alive_cnt[j];i++) {
tmpu=&units[j][i];
tmpu->player=j;
tmpu->num=i;
tmpu->life=100;
tmpu->facing=RandU16%6;
if (!j) {
if (i>=UNITS_NUM/2) {
if (i>=15*UNITS_NUM/16)
type=UT_ARTILLERY;
else
type=UT_INFANTRY;
} else {
if (i>=UNITS_NUM/4)
type=UT_MD_TANK;
else
type=UT_LT_TANK;
}
} else {
if (i>=UNITS_NUM/2) {
if (i>=15*UNITS_NUM/16)
type=UT_ARTILLERY;
else
type=UT_INFANTRY;
} else {
if (i>=UNITS_NUM/4)
type=UT_MD_TANK;
else
type=UT_LT_TANK;
}
}
tmpu->type=type;
switch (type) {
case UT_INFANTRY:
tmpu->infantry=TRUE;
tmpu->indirect_fire=FALSE;
tmpu->armor =0;
tmpu->armored_attack =15;
tmpu->unarmored_attack=180;
tmpu->accuracy=45;
tmpu->range =5;
tmpu->movement=4;
tmpu->img =$IB,"<1>",BI=1$;
break;
case UT_ARTILLERY:
tmpu->infantry=TRUE;
tmpu->indirect_fire=TRUE;
tmpu->armor =0;
tmpu->armored_attack =60;
tmpu->unarmored_attack=180;
tmpu->accuracy=25;
tmpu->range =20;
tmpu->movement=2;
tmpu->img =$IB,"<2>",BI=2$;
break;
case UT_LT_TANK:
tmpu->infantry=FALSE;
tmpu->indirect_fire=FALSE;
tmpu->armor =30;
tmpu->armored_attack =40;
tmpu->unarmored_attack=60;
tmpu->accuracy=25;
tmpu->range =8;
tmpu->movement=24;
tmpu->img =$IB,"<3>",BI=3$;
break;
case UT_MD_TANK:
tmpu->infantry=FALSE;
tmpu->indirect_fire=FALSE;
tmpu->armor =60;
tmpu->armored_attack =60;
tmpu->unarmored_attack=80;
tmpu->accuracy=25;
tmpu->range =12;
tmpu->movement=16;
tmpu->img =$IB,"<4>",BI=4$;
break;
}
do {
row=RandU32%map_rows;
col=RandU32%(map_cols/3);
if (j)
col+=2*map_cols/3;
} while (UnitFind(row,col));
tmpu->row=row;
tmpu->col=col;
LBts(&tmpu->vis[cur_player],0);
}
}
U0 ViewPlayerSet(I8 p)
{
CMenuEntry *tmpse;
view_player=p;
if (tmpse=MenuEntryFind(Fs->cur_menu,"View/Player1"))
tmpse->checked= view_player==0;
if (tmpse=MenuEntryFind(Fs->cur_menu,"View/Player2"))
tmpse->checked= view_player==1;
}
U0 Init()
{
DocClear;
"GameSeed(0x%X)\n",Seed(PopUpGetI64("GameSeed(0x%X):",Seed));
moving_unit=NULL;
InitMap;
ViewPlayerSet(cur_player=0);
enemy_player=1;
if (map_width<GR_WIDTH) {
x0=(MAP_WIDTH-map_width)>>1;
y0=(MAP_HEIGHT-map_height)>>1+FONT_HEIGHT;
} else {
x0=0;
y0=FONT_HEIGHT;
}
InitUnits;
QueInit(&indirect_head);
turn=0;
fire_radius=0;
show_vis_row=-1;
show_vis_col=-1;
*msg_buf=0;
msg_off_timeout=0;
phase=PHASE_END;
}
U0 CleanUp()
{
QueDel(&indirect_head,TRUE);
}
U0 PlayerPick(U8 *dirname,I64 player)
{
I64 i=0;
U8 *st;
CDirEntry *tmpde,*tmpde1,*tmpde2;
CDoc *doc=DocNew;
Bool *old_silent=Silent;
st=MStrPrint("%s/*.HC*",dirname);
tmpde=FilesFind(st);
Free(st);
tmpde2=FilesFind("~/ToTheFront/*.HC*");
tmpde1=tmpde;
Silent(old_silent);
DocPrint(doc,"Player %d Type\n\n$$LTBLUE$$",player+1);
while (tmpde1) {
if (!(i++&3))
DocPrint(doc,"\n");
st=StrNew(tmpde1->name);
FileExtRem(st);
tmpde1->user_data=DocPrint(doc,"$$MU-UL,\"%-10ts\",LE=%d$$ ",st,tmpde1);
Free(st);
tmpde1=tmpde1->next;
}
tmpde1=tmpde2;
while (tmpde1) {
if (!(i++&3))
DocPrint(doc,"\n");
st=StrNew(tmpde1->name);
FileExtRem(st);
tmpde1->user_data=DocPrint(doc,"$$MU-UL,\"%-10ts\",LE=%d$$ ",st,tmpde1);
Free(st);
tmpde1=tmpde1->next;
}
DocPrint(doc,"\n\n\n$$FG$$Create your own AI in ~/ToTheFront.");
while ((tmpde1=PopUpMenu(doc))<=0);
ExeFile(tmpde1->full_name);
DocDel(doc);
DirTreeDel(tmpde);
DirTreeDel(tmpde2);
ExePrint("player_indirect[%d]=&PlayerIndirect;"
"player_move[%d]=&PlayerMove;"
"player_direct[%d]=&PlayerDirect;",
player,player,player);
}
L ÿÿÿÿüÿÿÿ úÿÿÿ üÿÿÿúÿÿÿþÿÿÿ
øÿÿÿ üÿÿÿüÿÿÿ
ûÿÿÿûÿÿÿûÿÿÿ
ûÿÿÿ
ûÿÿÿ
ûÿÿÿûÿÿÿûÿÿÿ
üÿÿÿüÿÿÿ
üÿÿÿüÿÿÿG ÿÿÿÿýÿÿÿ
üÿÿÿ
þÿÿÿüÿÿÿþÿÿÿ
úÿÿÿÏ þÿÿÿþÿÿÿ
ÿÿÿÿýÿÿÿýÿÿÿ
ÿÿÿÿüÿÿÿüÿÿÿ
üÿÿÿ
ýÿÿÿ
þÿÿÿûÿÿÿûÿÿÿ
ýÿÿÿüÿÿÿ
þÿÿÿýÿÿÿþÿÿÿüÿÿÿ
ýÿÿÿýÿÿÿýÿÿÿ
ýÿÿÿ

ÿÿÿÿÿÿÿÿ
+121
View File
@@ -0,0 +1,121 @@
U0 Toward(I64 *_row,I64 *_col,I64 direction)
{
switch (direction) {
case 0:
*_row-=2;
break;
case 1:
if (*_row&1) *_col+=1;
*_row-=1;
break;
case 2:
if (*_row&1) *_col+=1;
*_row+=1;
break;
case 3:
*_row+=2;
break;
case 4:
if (!(*_row&1)) *_col-=1;
*_row+=1;
break;
case 5:
if (!(*_row&1)) *_col-=1;
*_row-=1;
break;
}
}
I64 FacingChg(I64 f1,I64 f2)
{
I64 res=(f1+6-f2)%6;
if (res>=3)
return 6-res;
else
return res;
}
U0 RowCol2XY(F64 *_x,F64 *_y,I64 row,I64 col)
{
Pt *c;
row=ClampI64(row,0,map_rows);
col=ClampI64(col,0,map_cols);
c=&hex_centers[row][col];
*_x=c->x;
*_y=c->y;
}
U0 XY2RowCol(I64 *_row,I64 *_col,F64 x,F64 y)
{
*_col=(x-DCOS/2)/(HEX_SIDE+DCOS);
if (*_col&1)
*_row=ToI64((y-DSIN)/(2*DSIN))*2+1;
else
*_row=ToI64(y/(2*DSIN))*2;
*_col>>=1;
*_row=ClampI64(*_row,0,map_rows-1);
*_col=ClampI64(*_col,0,map_cols-1);
}
Unit *UnitFind(I64 row,I64 col)
{//Finds unit in a hexagon.
I64 i,j;
for (j=0;j<2;j++)
for (i=0;i<UNITS_NUM;i++)
if (units[j][i].life>0 &&
units[j][i].row==row &&
units[j][i].col==col)
return &units[j][i];
return NULL;
}
Bool CursorInWin(CTask *task,I64 x,I64 y)
{
if (0<=x+task->scroll_x<task->pix_width &&
0<=y+task->scroll_y<task->pix_height)
return TRUE;
else
return FALSE;
}
U0 CursorUpdate(CTask *task,I64 x,I64 y)
{
if (CursorInWin(task,x,y))
XY2RowCol(&cursor_row,&cursor_col,x,y);
}
class LOSCtrl
{
I64 r1,c1,r2,c2,distance;
};
Bool LOSPlot(LOSCtrl *l,I64 x,I64 y,I64 z)
{//We got tricky and used z as the distance from the start of the line.
I64 row,col;
XY2RowCol(&row,&col,x,y);
if ((row!=l->r1 || col!=l->c1) &&
(row!=l->r2 || col!=l->c2) &&
terrain[row][col]!=PLAINS) {
if (terrain[l->r1][l->c1]==MOUNTAINS) {
if (terrain[row][col]==MOUNTAINS || z>l->distance>>1)
return FALSE;
} else if (terrain[l->r2][l->c2]==MOUNTAINS) {
if (terrain[row][col]==MOUNTAINS || z<=l->distance>>1)
return FALSE;
} else
return FALSE;
}
return TRUE;
}
Bool LOS(I64 r1,I64 c1,I64 r2,I64 c2)
{
F64 x1,y1,x2,y2;
LOSCtrl l;
RowCol2XY(&x1,&y1,r1,c1);
RowCol2XY(&x2,&y2,r2,c2);
l.r1=r1; l.c1=c1;
l.r2=r2; l.c2=c2;
l.distance=Sqrt(SqrI64(x1-x2)+SqrI64(y1-y2));
return Line(&l,x1,y1,0,x2,y2,l.distance,&LOSPlot);
}
+129
View File
@@ -0,0 +1,129 @@
U8 movement_costs[16];
movement_costs[PLAINS]=2;
movement_costs[TREES]=6;
movement_costs[MOUNTAINS]=10;
I64 HexMoveOneCost(Unit *tmpu,I64 r,I64 c,I64 facing)
{
I64 res;
if (tmpu->infantry)
res=0;
else {
res=FacingChg(facing,tmpu->facing);
if (res>0) res--;
}
if (roads[r][c] && roads[tmpu->row][tmpu->col])
res+=1;
else {
if (tmpu->infantry)
res+=2;
else {
res+=movement_costs[terrain[r][c]];
if (rivers[r][c])
res=tmpu->movement;
}
}
return res;
}
I64 HexMoveOne(I64 *_row,I64 *_col,F64 x,F64 y)
{
I64 direction,best_direction=-1,r,c;
F64 dd,best_dd,x1,y1;
RowCol2XY(&x1,&y1,*_row,*_col);
best_dd=Sqr(x1-x)+Sqr(y1-y);
for (direction=0;direction<6;direction++) {
r=*_row; c=*_col;
Toward(&r,&c,direction);
RowCol2XY(&x1,&y1,r,c);
dd=Sqr(x1-x)+Sqr(y1-y);
if (0<=r<map_rows && 0<=c<map_cols && dd<best_dd) {
best_dd=dd;
best_direction=direction;
}
}
if (best_direction>=0) {
Toward(_row,_col,best_direction);
return best_direction;
} else
return -1;
}
Bool UnitMovePlot(U0,I64 x,I64 y,I64)
{
move_x=x; move_y=y;
Sleep(5*animation_delay);
return TRUE;
}
U0 UnitMoveAnimation(Unit *tmpu,I64 r,I64 c,I64 facing)
{
F64 x1,y1,x2,y2,f=facing*60.0*ã/180.0;
moving_unit=tmpu;
RowCol2XY(&x1,&y1,tmpu->row,tmpu->col);
move_x=x1; move_y=y1;
moving=TRUE;
if (tmpu->infantry)
Snd(53);
else {
move_facing=tmpu->facing*60.0*ã/180.0;
Snd(41);
while (Wrap(f-move_facing,-ã)<=0) {
move_facing-=0.03;
Sleep(5*animation_delay);
}
while (Wrap(f-move_facing,-ã)>0) {
move_facing+=0.03;
Sleep(5*animation_delay);
}
Snd(34);
}
move_facing=f;
RowCol2XY(&x2,&y2,r,c);
Line(NULL,x1,y1,0,x2,y2,0,&UnitMovePlot);
Snd;
moving_unit=NULL;
moving=FALSE;
}
Bool UnitMove(Unit *tmpu,I64 x,I64 y)
{
Unit *target;
I64 r,c,r0=tmpu->row,c0=tmpu->col,i,facing;
while (tmpu->remaining_movement>0) {
r=tmpu->row;
c=tmpu->col;
if ((facing=HexMoveOne(&r,&c,x,y))<0)
break;
else {
i=HexMoveOneCost(tmpu,r,c,facing);
if (i>tmpu->movement)
i=tmpu->movement;
if (!tmpu->fired && tmpu->remaining_movement>=i &&
tmpu->remaining_movement>=tmpu->movement>>1 &&
(target=UnitFind(r,c)) && target->player!=tmpu->player &&
tmpu->infantry!=target->infantry) {
if (!HexOccupy(ToBool(target->infantry),tmpu,target)) {
tmpu=NULL;
break;
}
i=tmpu->remaining_movement;
}
if (tmpu->remaining_movement>=i && !UnitFind(r,c)) {
UnitMoveAnimation(tmpu,r,c,facing);
tmpu->facing=facing;
tmpu->remaining_movement-=i;
tmpu->row=r;
tmpu->col=c;
VisRecalc(VR_UPDATE_FRIENDLY_UNIT,tmpu);
LBEqu(&tmpu->vis[enemy_player],0,
VisRecalc(VR_ONE_ENEMY_UNIT,tmpu));
} else
break;
}
}
if (!tmpu || tmpu->row!=r0 || tmpu->col!=c0)
return TRUE;
else
return FALSE;
}
+223
View File
@@ -0,0 +1,223 @@
#define VR_ONE_FRIENDLY_UNIT 0
#define VR_UPDATE_FRIENDLY_UNIT 1
#define VR_FRIENDLY_UNIT_DIED 3
#define VR_ONE_ENEMY_UNIT 4
#define VR_ALL_UNITS 5
class MPCtrl1
{
I64 mode,lo,hi;
Unit *tmpu;
};
class MPCtrl2
{
I64 lo,hi,row,col;
};
U0 VRSetUp(I64 player)
{
I64 i;
Unit *ut0,*ut1;
ut0=&units[player][0];
ut1=&units[player^1][0];
for (i=0;i<UNITS_NUM;i++,ut0++,ut1++) {
LBtr(&ut1->vis[player],0);
LBEqu(&ut0->vis[player],0,ut0->life>0);
}
}
U0 VRMerge(I64 player)
{
I64 i,j;
Unit *ut1;
U8 *dst,*src,*mask=CAlloc((UNITS_NUM+7)>>3);
for (j=0;j<UNITS_NUM;j++) {//p0
src=&vis_unit_bitmap[player][(((UNITS_NUM+7)&~7)*j)>>3];
dst=mask;
for (i=0;i<(UNITS_NUM+7)>>3;i++) //player1
*dst++|=*src++;
}
ut1=&units[player^1][0];
for (j=0;j<UNITS_NUM;j++,ut1++)
LBEqu(&ut1->vis[player],0,Bt(mask,j) && ut1->life>0);
Free(mask);
}
Bool MPVisRecalc(MPCtrl1 *job)
{
Bool res=FALSE,seen;
I64 i,j,row,col;
F64 x1,y1,x2,y2,dd,range;
Unit *ut0,*ut1;
ut0=&units[cur_player][job->lo];
ut1=&units[enemy_player][job->lo];
if (job->tmpu) {
row=job->tmpu->row;
col=job->tmpu->col;
range=job->tmpu->range*2*HEX_RADIUS;
range*=range;
}
switch (job->mode) {
case VR_UPDATE_FRIENDLY_UNIT:
case VR_ONE_FRIENDLY_UNIT:
if (job->mode==VR_UPDATE_FRIENDLY_UNIT)
range=F64_MAX;
RowCol2XY(&x1,&y1,row,col);
for (i=job->lo;i<job->hi;i++,ut1++) {
seen=FALSE;
if (ut1->life>0 &&
LOS(row,col,ut1->row,ut1->col)) {
RowCol2XY(&x2,&y2,ut1->row,ut1->col);
dd=Sqr(x2-x1)+Sqr(y2-y1);
if (dd<range) {
seen=TRUE;
LBts(&ut1->vis[cur_player],0);
}
}
if (job->mode==VR_UPDATE_FRIENDLY_UNIT)
LBEqu(&vis_unit_bitmap[cur_player],
i+job->tmpu->num*((UNITS_NUM+7)&~7),seen);
}
break;
case VR_ONE_ENEMY_UNIT:
RowCol2XY(&x1,&y1,row,col);
for (i=job->lo;i<job->hi;i++,ut1++)
if (ut1->life>0 &&
LOS(row,col,ut1->row,ut1->col)) {
LBts(&vis_unit_bitmap[enemy_player],
job->tmpu->num+i*((UNITS_NUM+7)&~7));
res=TRUE;
} else
LBtr(&vis_unit_bitmap[enemy_player],
job->tmpu->num+i*((UNITS_NUM+7)&~7));
break;
case VR_ALL_UNITS:
ut0=&units[cur_player][0];
for (i=0;i<UNITS_NUM;i++,ut0++)
if (ut0->life>0) {
RowCol2XY(&x1,&y1,ut0->row,ut0->col);
ut1=&units[enemy_player][job->lo];
for (j=job->lo;j<job->hi;j++,ut1++) {
if (ut1->life>0 &&
LOS(ut0->row,ut0->col,ut1->row,ut1->col)) {
LBts(&ut1->vis[cur_player],0);
LBts(&vis_unit_bitmap[cur_player],j+i*((UNITS_NUM+7)&~7));
} else
LBtr(&vis_unit_bitmap[cur_player],j+i*((UNITS_NUM+7)&~7));
}
} else
for (j=job->lo;j<job->hi;j++)
LBtr(&vis_unit_bitmap[cur_player],j+i*((UNITS_NUM+7)&~7));
ut0=&units[enemy_player][0];
for (i=0;i<UNITS_NUM;i++,ut0++)
if (ut0->life>0) {
RowCol2XY(&x1,&y1,ut0->row,ut0->col);
ut1=&units[cur_player][job->lo];
for (j=job->lo;j<job->hi;j++,ut1++) {
if (ut1->life>0 &&
LOS(ut0->row,ut0->col,ut1->row,ut1->col)) {
LBts(&ut1->vis[enemy_player],0);
LBts(&vis_unit_bitmap[enemy_player],j+i*((UNITS_NUM+7)&~7));
} else
LBtr(&vis_unit_bitmap[enemy_player],j+i*((UNITS_NUM+7)&~7));
}
} else
for (j=job->lo;j<job->hi;j++)
LBtr(&vis_unit_bitmap[enemy_player],j+i*((UNITS_NUM+7)&~7));
break;
}
return res;
}
Bool VisRecalc(I64 mode,Unit *tmpu=NULL)
{
I64 i,hi,k,cnt;
Bool res;
/*The compiler doesn't go out of it's way
to know if something is const.;-) This
just compiles with the val at compile
time, an advantage of just-in-time over
AOT binaries. TempleOS has a limited
stk size, so don't get in the habit.
$LK,"MAlloc",A="MN:MAlloc"$() would probably be the better choice.
*/
MPCtrl1 job[mp_cnt];
CJob *cmd[mp_cnt];
if (mode==VR_FRIENDLY_UNIT_DIED) {
MemSet((&vis_unit_bitmap[enemy_player])(U8 *)+
(tmpu->num*((UNITS_NUM+7)&~7))>>3,0,(UNITS_NUM+7)>>3);
VRMerge(enemy_player);
return 0; //Return any value--don't care
}
cnt=mp_cnt; //Cores
hi=UNITS_NUM;
if (mode==VR_ONE_ENEMY_UNIT) {
for (hi--;hi>=0;hi--)
if (units[enemy_player][hi].life>0)
break;
hi++;
}
k=hi;
if (hi/mp_cnt<2)
cnt=1;
for (i=0;i<cnt;i++) {
job[i].mode=mode;
job[i].tmpu=tmpu;
job[i].hi=k;
k-=hi/cnt;
if (k<0) k=0;
if (i==cnt-1) k=0;
job[i].lo=k;
}
res=FALSE;
for (i=0;i<cnt;i++)
cmd[i]=JobQue(&MPVisRecalc,&job[i],i,0);
for (i=0;i<cnt;i++)
if (JobResGet(cmd[i]))
res=TRUE;
if (mode==VR_UPDATE_FRIENDLY_UNIT)
VRMerge(cur_player);
return res;
}
U0 MPVisRecalcMap(MPCtrl2 *job)
{
I64 i,j;
for (j=job->lo;j<job->hi;j++)
for (i=0;i<map_cols;i++)
if (LOS(job->row,job->col,j,i))
vis_map[j][i]=TRUE;
else
vis_map[j][i]=FALSE;
}
U0 VisRecalcMap(I64 row,I64 col)
{
I64 i,hi,k,cnt;
MPCtrl2 job[mp_cnt];
CJob *cmd[mp_cnt];
cnt=mp_cnt; //Cores
hi=map_rows;
k=hi;
if (hi/mp_cnt<2)
cnt=1;
for (i=0;i<cnt;i++) {
job[i].row=row;
job[i].col=col;
job[i].hi=k;
k-=hi/cnt;
if (k<0) k=0;
if (i==cnt-1) k=0;
job[i].lo=k;
}
for (i=0;i<cnt;i++)
cmd[i]=JobQue(&MPVisRecalcMap,&job[i],i,0);
for (i=0;i<cnt;i++)
JobResGet(cmd[i]);
}
+214
View File
@@ -0,0 +1,214 @@
U0 AnimationDelaySet()
{
animation_delay=PopUpRangeF64(0,100,25,"%3f% %%","Animation Delay\n")/100;
}
U0 TurnNew()
{
I64 i,j;
for (j=0;j<2;j++)
for (i=0;i<UNITS_NUM;i++) {
units[j][i].remaining_movement=units[j][i].movement;
units[j][i].fired=FALSE;
}
phase=PHASE_START;
moving_unit=NULL;
SleepUntil(msg_off_timeout);
msg_off_timeout=cnts.jiffies+JIFFY_FREQ*2*animation_delay+1;
Snd(74);
StrPrint(msg_buf,"Turn %d",++turn);
VRSetUp(0);
VRSetUp(1);
VisRecalc(VR_ALL_UNITS);
cur_player=(turn&1)^1;
enemy_player=cur_player^1;
}
U0 PhaseNew()
{
cur_player^=1;
enemy_player=cur_player^1;
if (++phase>=PHASE_END) {
IndirectResolveAll;
TurnNew;
}
SleepUntil(msg_off_timeout);
msg_off_timeout=cnts.jiffies+JIFFY_FREQ*2*animation_delay+1;
Snd(74);
switch (phase) {
case PHASE_INDIRECT0:
case PHASE_INDIRECT1:
StrPrint(msg_buf,"Player %d Artillery Plot",cur_player+1);
break;
case PHASE_MOVE0:
case PHASE_MOVE1:
StrPrint(msg_buf,"Player %d Move",cur_player+1);
break;
case PHASE_DIRECT0:
case PHASE_DIRECT1:
StrPrint(msg_buf,"Player %d Fire",cur_player+1);
break;
}
}
U0 CharDo(U8 ch)
{
I64 old_inhibit,old_draw_it;
Bool old_cursor;
switch (ch) {
case CH_ESC:
case CH_SHIFT_ESC:
throw('ExitGame',TRUE);
case CH_SPACE:
throw('PhaseOvr',TRUE);
case '\n':
throw('NewGame',TRUE);
case '1':
ViewPlayerSet(0);
break;
case '2':
ViewPlayerSet(1);
break;
case 'c':
old_draw_it=Fs->draw_it;
old_inhibit=Fs->win_inhibit;
Fs->draw_it=Fs->next_settings->draw_it;
Fs->win_inhibit=WIG_USER_TASK_DFT;
old_cursor=DocCursor(ON);
DocBottom;
"\n$$GREEN$$<SHIFT-ESC>$$FG$$ to return to game.\n";
View;
DocBottom;
DocCursor(old_cursor);
Fs->win_inhibit=old_inhibit;
Fs->draw_it=old_draw_it;
break;
case 'd':
AnimationDelaySet;
break;
}
}
U0 UserChk()
{
I64 ch;
if (!alive_cnt[0] || !alive_cnt[1])
throw('GameOver',TRUE);
if (ch=ScanChar)
CharDo(ch);
}
U0 TaskEndCB()
{
Snd;
progress4=progress4_max=progress1=progress1_max=0;
Exit;
}
I64 PhaseDo()
{
I64 res='ExitGame';
PhaseNew;
try {
if (phase&~1==PHASE_INDIRECT)
Call(player_indirect[cur_player]);
else if (phase&~1==PHASE_MOVE)
Call(player_move[cur_player]);
else
Call(player_direct[cur_player]);
} catch {
res=Fs->except_ch;
Fs->catch_except=TRUE;
}
return res;
}
U0 ToTheFront()
{
I64 res,ch;
map_dc=DCNew(MAP_WIDTH,MAP_HEIGHT);
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
Cd(__DIR__);
Fs->win_inhibit|=WIF_SELF_MS_L|WIF_SELF_MS_R|WIG_DBL_CLICK;
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" EndPhase(,CH_SPACE);"
" Restart(,'\n');"
"}"
"View {"
" Player1(,'1');"
" Player2(,'2');"
" OddsCalculations(,'c');"
" LOS(,0,SCF_SHIFT);"
"}"
"Settings {"
" AnimationDelay(,'d');"
"}"
);
AutoComplete;
WinBorder;
WinMax;
DocCursor;
DocMax;
Init;
PlayerPick("AIs",0);
PlayerPick("AIs",1);
PopUpOk("$$PURPLE$$$$TX+CX,\"ToTheFront\"$$$$FG$$\n\n"
"$$GREEN$${Left-click}$$FG$$ to move or fire units.\n"
"$$GREEN$$<SPACE>$$FG$$\tor $$GREEN$${Right-click}$$FG$$ to end phase.\n"
"$$GREEN$$<SHIFT>$$FG$$\tto show line-of-sight.\n"
"$$GREEN$$<ENTER>$$FG$$\tto start new game.\n"
"$$GREEN$$ 1$$FG$$\tPlayer 1 view.\n"
"$$GREEN$$ 2$$FG$$\tPlayer 2 view.\n"
"$$GREEN$$ c$$FG$$\tView odds calculations.\n"
"$$GREEN$$ d$$FG$$\tSet animation delay.");
Fs->task_end_cb=&TaskEndCB; //<CTRL-ALT-x>
Fs->draw_it=&DrawIt;
try {
do {
res=PhaseDo;
if (res=='GameOver') {
while (TRUE) {
msg_off_timeout=0;
StrCpy(msg_buf,"Game Over");
Snd;
ch=GetChar(,FALSE);
if (ch=='\n') {
CleanUp;
Init;
break;
} else if (ch==CH_ESC || ch==CH_SHIFT_ESC) {
res='ExitGame';
break;
} else if (ch=='1')
ViewPlayerSet(0);
else if (ch=='2')
ViewPlayerSet(1);
else if (ch=='d')
AnimationDelaySet;
}
} else if (res=='NewGame') {
CleanUp;
Init;
}
} while (res!='ExitGame');
} catch
PutExcept;
ProgressBarsRst;
SettingsPop;
MenuPop;
DCDel(map_dc);
CleanUp;
Seed;
}