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

+11
View File
@@ -0,0 +1,11 @@
$FG,6$JOB
$FG,1$BANK
$FG,4$CREDIT
$FG,2$CASH
$FG,0$RENT
CAR
UTILITIES
MISC
CLOTHS
HEALTH
CHARITY
+83
View File
@@ -0,0 +1,83 @@
U0 BgtAcctsUpdate()
{
CBgtEntry *tmpb;
CBgtTemplate *tmpt;
tmpb=b_head.next;
while (tmpb!=&b_head) {
if (tmpb->type!=BE_TEMPLATE_COPY) {
tmpb->credit_idx=StrFileAdd(tmpb->credit,
&accts_table_strs,accts_table);
tmpb->debit_idx =StrFileAdd(tmpb->debit,
&accts_table_strs,accts_table);
}
tmpb=tmpb->next;
}
tmpt=t_head.next;
while (tmpt!=&t_head) {
tmpt->b.credit_idx=StrFileAdd(tmpt->b.credit,
&accts_table_strs,accts_table);
tmpt->b.debit_idx =StrFileAdd(tmpt->b.debit,
&accts_table_strs,accts_table);
tmpt=tmpt->next;
}
}
U0 BgtAcctsWrite()
{
BgtAcctsUpdate;
StrFileWrite(BGT_ACCTS_FILE,accts_table,TRUE);
}
U0 BgtAcctsRead()
{
I64 i,max_num;
U8 *colors,**s=StrFileRead(BGT_ACCTS_FILE,&max_num,&colors,TRUE);
StrFileDel(accts_table);
accts_table=HashTableNew(512);
accts_table_strs=0;
for (i=0;i<=max_num;i++)
if (s[i])
StrFileAdd(s[i],&accts_table_strs,accts_table,colors[i]);
StrFileArrDel(s,max_num);
Free(colors);
}
I64 BgtAcctColor(U8 *st)
{
CHashGeneric *tmph;
if (tmph=HashFind(st,accts_table,SFT_GENERIC))
return tmph->user_data1;
else
return BLACK;
}
U8 *BgtPopUpAcct(U8 *header=NULL,U8 *dft=NULL)
{
I64 i;
U8 *res;
CDoc *doc=DocNew;
CDocEntry *doc_e,*doc_dft=NULL;
CHashGeneric *tmph;
if (header)
DocPrint(doc,"%s",header);
for (i=0;i<=accts_table->mask;i++) {
tmph=accts_table->body[i];
while (tmph) {
doc_e=DocPrint(doc,"$$FG,%d$$$$MU-UL,\"%s\",LE=0x%X$$\n",
tmph->user_data1,tmph->str,tmph->str);
if (dft && !StrCmp(dft,tmph->str))
doc_dft=doc_e;
tmph=tmph->next;
}
}
if (doc_dft) {
doc->cur_entry=doc_dft;
doc->cur_col=0;
}
res=PopUpMenu(doc,DOF_DONT_HOME);
DocDel(doc);
return res;
}
+83
View File
@@ -0,0 +1,83 @@
U0 BgtEntryDel2(CBgtEntry *tmpb)
{
if (tmpb->type!=BE_TEMPLATE_COPY) {
Free(tmpb->credit);
Free(tmpb->debit);
Free(tmpb->desc);
}
}
CBgtEntry *BgtEntryCopy(CBgtEntry *tmpb,Bool periodic_copy)
{
CBgtEntry *res=MAlloc(sizeof(CBgtEntry));
MemCpy(res,tmpb,sizeof(CBgtEntry));
if (periodic_copy) {
res->credit=StrNew(tmpb->credit);
res->debit =StrNew(tmpb->debit);
res->desc =StrNew(tmpb->desc);
}
return res;
}
U0 BgtEntryDel(CBgtEntry *tmpb)
{
BgtEntryDel2(tmpb);
Free(tmpb);
}
U0 BgtIns(CBgtEntry *tmpb)
{
CBgtEntry *tmpb1=b_head.next;
while (tmpb1!=&b_head && tmpb1->date<tmpb->date)
tmpb1=tmpb1->next;
QueIns(tmpb,tmpb1->last);
}
class CBgtEntryForm
{
U8 date[512] fmtstr "$$DA-P,A=\"Date :%s\"$$\n";
F64 amount fmtstr "Amount $$$$$$DA,A=\"%10.2f\"$$\n";
U8 credit[512] fmtstr "$$DA-P,A=\"Credit (from) Acct:%s\"$$\n";
U8 debit [512] fmtstr "$$DA-P,A=\"Debit (to) Acct:%s\"$$\n";
U8 desc [512] fmtstr "$$DA-P,A=\"Desc :%s\"$$\n";
};
CBgtEntry *BgtEntryPmt(CBgtEntry *dft=NULL)
{
CBgtEntryForm b;
CBgtEntry *tmpb;
U8 *st;
MemSet(&b,0,sizeof(CBgtEntryForm));
StrCpy(&b.date,"*");
if (dft) {
StrPrint(b.date,"%D",dft->date);
b.amount=dft->amount;
StrCpy(b.credit,dft->credit);
StrCpy(b.debit ,dft->debit);
StrCpy(b.desc ,dft->desc);
}
while (TRUE)
if (PopUpForm(&b)) {
if (!*b.credit) {
st=BgtPopUpAcct("Credit Acct\n\n");
if (st!=DOCM_CANCEL)
StrCpy(b.credit,st);
} else if (!*b.debit) {
st=BgtPopUpAcct("Debit Acct\n\n");
if (st!=DOCM_CANCEL)
StrCpy(b.debit,st);
} else {
tmpb=CAlloc(sizeof(CBgtEntry));
tmpb->date =Str2Date(b.date);
tmpb->amount=b.amount;
tmpb->credit=StrNew(b.credit);
tmpb->debit =StrNew(b.debit);
tmpb->desc =StrNew(b.desc);
tmpb->type =BE_NORMAL;
StrFileAdd(tmpb->credit,&accts_table_strs,accts_table);
StrFileAdd(tmpb->debit,&accts_table_strs,accts_table);
return tmpb;
}
} else
return NULL;
}
+140
View File
@@ -0,0 +1,140 @@
U0 BgtDataRead()
{
CBgtEntry *tmpb;
CBgtTemplate *tmpt;
I64 i,cnt,size;
U8 *b,*ptr;
I64 max_num;
U8 **s=StrFileRead(BGT_STRINGS_FILE,&max_num);
MemSet(&b_head,0,sizeof(CBgtEntry));
QueInit(&b_head);
b_head.date=Now;
MemSet(&t_head,0,sizeof(CBgtTemplate));
QueInit(&t_head);
t_head.b.date=Now;
if (ptr=b=FileRead(BGT_DATA_FILE,&size)) {
cnt=*ptr(I64 *)++;
for (i=0;i<cnt;i++) {
tmpb=CAlloc(sizeof(CBgtEntry));
MemCpy(&tmpb->start,ptr,BE_SIZE);
tmpb->credit=StrNew(s[tmpb->credit_idx]);
tmpb->debit =StrNew(s[tmpb->debit_idx]);
tmpb->desc =StrNew(s[tmpb->desc_idx]);
QueIns(tmpb,b_head.last);
ptr+=BE_SIZE;
}
cnt=*ptr(I64 *)++;
for (i=0;i<cnt;i++) {
tmpt=CAlloc(sizeof(CBgtTemplate));
MemCpy(&tmpt->start,ptr,BT_SIZE);
ptr+=BT_SIZE;
MemCpy(&tmpt->b.start,ptr,BE_SIZE);
ptr+=BE_SIZE;
tmpt->b.credit=StrNew(s[tmpt->b.credit_idx]);
tmpt->b.debit =StrNew(s[tmpt->b.debit_idx]);
tmpt->b.desc =StrNew(s[tmpt->b.desc_idx]);
QueIns(tmpt,t_head.last);
}
}
StrFileArrDel(s,max_num);
Free(b);
BgtAcctsUpdate;
}
U0 BgtDataWrite()
{
I64 i,num=0,size,cnt1,cnt2;
CHashTable *table=HashTableNew(1024);
CBgtEntry *tmpb;
CBgtTemplate *tmpt;
CHashGeneric *tmph;
U8 *buf,*ptr;
for (i=0;i<=accts_table->mask;i++) {
tmph=accts_table->body[i];
while (tmph) {
StrFileAdd(tmph->str,&num,table); //Cosmetics -- make accts appear first.
tmph=tmph->next;
}
}
tmpb=b_head.next;
cnt1=0;
while (tmpb!=&b_head) {
if (tmpb->type!=BE_TEMPLATE_COPY) {
tmpb->credit_idx =StrFileAdd(tmpb->credit,&num,table);
tmpb->debit_idx =StrFileAdd(tmpb->debit,&num,table);
tmpb->desc_idx =StrFileAdd(tmpb->desc,&num,table);
cnt1++;
}
tmpb=tmpb->next;
}
tmpt=t_head.next;
cnt2=0;
while (tmpt!=&t_head) {
tmpt->b.credit_idx =StrFileAdd(tmpt->b.credit,&num,table);
tmpt->b.debit_idx =StrFileAdd(tmpt->b.debit,&num,table);
tmpt->b.desc_idx =StrFileAdd(tmpt->b.desc,&num,table);
cnt2++;
tmpt=tmpt->next;
}
StrFileWrite(BGT_STRINGS_FILE,table);
StrFileDel(table);
size=sizeof(I64)*2+cnt1*BE_SIZE+cnt2*(BT_SIZE+BE_SIZE);
buf=ptr=MAlloc(size);
MemCpy(ptr,&cnt1,sizeof(I64));
ptr+=sizeof(I64);
tmpb=b_head.next;
while (tmpb!=&b_head) {
if (tmpb->type!=BE_TEMPLATE_COPY) {
MemCpy(ptr,&tmpb->start,BE_SIZE);
ptr+=BE_SIZE;
}
tmpb=tmpb->next;
}
MemCpy(ptr,&cnt2,sizeof(I64));
ptr+=sizeof(I64);
tmpt=t_head.next;
while (tmpt!=&t_head) {
MemCpy(ptr,&tmpt->start,BT_SIZE);
ptr+=BT_SIZE;
MemCpy(ptr,&tmpt->b.start,BE_SIZE);
ptr+=BE_SIZE;
tmpt=tmpt->next;
}
FileWrite(BGT_DATA_FILE,buf,size);
Free(buf);
}
U0 BgtDel()
{
CBgtEntry *tmpb,*tmpb1;
CBgtTemplate *tmpt,*tmpt1;
tmpb=b_head.next;
while (tmpb!=&b_head) {
tmpb1=tmpb->next;
BgtEntryDel2(tmpb);
Free(tmpb);
tmpb=tmpb1;
}
tmpt=t_head.next;
while (tmpt!=&t_head) {
tmpt1=tmpt->next;
BgtEntryDel2(&tmpt->b);
Free(tmpt);
tmpt=tmpt1;
}
StrFileDel(accts_table);
accts_table=NULL;
accts_table_strs=0;
}
+224
View File
@@ -0,0 +1,224 @@
extern U0 BgtRegen();
Bool BgtPutKey(CDoc *doc,U8 *,I64 ch,I64 sc)
{//ch=ASCII; sc=scan_code
no_warn sc;
CBgtEntry *tmpb,*tmpb1;
CBgtTemplate *tmpt,*tmpt1;
CDocEntry *doc_ce;
U8 *st;
switch (ch) {
case '\n':
if ((doc_ce=doc->cur_entry) && doc_ce!=doc &&
doc_ce->type_u8==DOCT_MENU_VAL) {
tmpb=doc_ce->user_data;
if (tmpt=tmpb->template) {
if (tmpt1=BgtTemplatePmt(tmpt)) {
QueRem(tmpt);
BgtTemplatePurge(tmpt);
BgtEntryDel2(&tmpt->b);
Free(tmpt);
QueIns(tmpt1,t_head.last);
BgtTemplateExpand(tmpt1);
BgtRegen;
}
} else {
if (tmpb1=BgtEntryPmt(tmpb)) {
QueRem(tmpb);
BgtEntryDel(tmpb);
BgtIns(tmpb1);
BgtRegen;
}
}
}
return TRUE;
case CH_CTRLY:
if ((doc_ce=doc->cur_entry) && doc_ce!=doc &&
doc_ce->type_u8==DOCT_MENU_VAL) {
tmpb=doc_ce->user_data;
if (tmpt=tmpb->template) {
QueRem(tmpt);
BgtTemplateDel(tmpt);
} else {
QueRem(tmpb);
BgtEntryDel(tmpb);
}
BgtRegen;
}
return TRUE;
case 'a':
PopUpOk( "Set the name and color of your accounts.\n"
"To delete accounts, manually edit\n"
"$$GREEN$$~/Budget/Accts.DD.Z$$FG$$.");
if (PopUpEd(BGT_ACCTS_FILE,Fs)) {
BgtAcctsRead;
BgtRegen;
}
return TRUE;
case 'v':
if ((st=BgtPopUpAcct("View Acct\n\n",view_acct))>=0) {
StrCpy(view_acct,st);
BgtRegen;
}
return TRUE;
case 'n':
if (tmpb1=BgtEntryPmt) {
BgtIns(tmpb1);
BgtRegen;
}
return TRUE;
case 't':
if (tmpt1=BgtTemplatePmt) {
QueIns(tmpt1,t_head.last);
BgtTemplateExpand(tmpt1);
BgtRegen;
}
return TRUE;
case 'c':
if ((doc_ce=doc->cur_entry) && doc_ce!=doc &&
doc_ce->type_u8==DOCT_MENU_VAL)
tmpb=doc_ce->user_data;
else
tmpb=NULL;
if (tmpb1=BgtEntryPmt(tmpb)) {
BgtIns(tmpb1);
BgtRegen;
}
return TRUE;
case 'p':
if ((doc_ce=doc->cur_entry) && doc_ce!=doc &&
doc_ce->type_u8==DOCT_MENU_VAL) {
tmpb=doc_ce->user_data;
if (tmpt1=BgtTemplatePmt(,tmpb)) {
BgtTemplateExpand(tmpt1,TRUE);
BgtTemplateDel(tmpt1);
BgtRegen;
}
}
return TRUE;
}
return FALSE;
}
U0 BgtRegen()
{
I64 timeout_jiffy,c,color=COLOR_INVALID;
F64 balance=0;
CDoc *doc,*pdoc,*ddoc;
CDocEntry *doc_ce;
CBgtEntry *tmpb=b_head.next,*tmpb_ce;
doc=DocNew;
doc->flags|=DOCF_FORM;
while (tmpb!=&b_head) {
if (!StrCmp(view_acct,tmpb->credit))
balance-=tmpb->amount;
if (!StrCmp(view_acct,tmpb->debit))
balance+=tmpb->amount;
c=BgtAcctColor(tmpb->credit);
if (c!=color) {
color=c;
DocPrint(doc,"$$FG,%d$$",color);
}
tmpb->doc_e=DocPrint(doc,
"$$MU-UL,\"%D %8ts %8ts:%8.2f %8.2f:%$$Q\",U=0x%X$$\n",
tmpb->date,tmpb->credit,tmpb->debit,balance,
tmpb->amount,tmpb->desc,tmpb);
tmpb=tmpb->next;
}
DocRecalc(doc);
if (pdoc=Fs->put_doc) {
DocLock(pdoc);
//Now, we want to preserve old position in doc, using ugly brute force.
//It's tricky -- can't use old line num because of editor filters.
//The price we pay for using the standard document editor is this kludge.
//When I originally wrote my budget program, I did not have separate budget
//and line entries, so we never had to resync.
doc_ce=pdoc->cur_entry;
timeout_jiffy=cnts.jiffies+JIFFY_FREQ; //Max one second.
while (doc_ce!=pdoc && cnts.jiffies<timeout_jiffy) {
while (doc_ce->type_u8!=DOCT_MENU_VAL || !(tmpb_ce=doc_ce->user_data)) {
doc_ce=doc_ce->next;
if (doc_ce==pdoc) goto br_cont;
}
tmpb=b_head.next;
while (tmpb!=&b_head) {
if (tmpb==tmpb_ce) {
doc->cur_entry=tmpb->doc_e;
doc->cur_col=0;
DocCenter(doc);
goto br_cont;
}
tmpb=tmpb->next;
}
doc_ce=doc_ce->next;
}
}
br_cont:
ddoc=Fs->display_doc;
Fs->put_doc =doc;
Fs->display_doc=doc;
DocDel(pdoc);
if (pdoc!=ddoc)
DocDel(ddoc);
doc->user_put_key=&BgtPutKey;
}
U0 Budget()
{
CDoc *pdoc,*ddoc,*old_put,*old_display;
BgtAcctsRead;
BgtDataRead;
CBgtTemplatesExpand;
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
AutoComplete;
WinBorder;
WinMax;
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Edit {"
" NewEntry(,'n');"
" CopyEntry(,'c');"
" PeriodicEntry(,'p');"
" EditEntry(,'\n');"
" DeleteEntry(,CH_CTRLY);"
" NewTemplate(,'t');"
" AcctsFile(,'a');"
"}"
"View {"
" ViewAcct(,'v');"
"}"
);
StrCpy(view_acct,"BANK");
DocMax;
old_put =Fs->put_doc;
old_display =Fs->display_doc;
Fs->put_doc =NULL;
Fs->display_doc=NULL;
BgtRegen;
try
if (View) {
BgtDataWrite;
BgtAcctsWrite;
}
catch
PutExcept;
pdoc=Fs->put_doc;
ddoc=Fs->display_doc;
Fs->put_doc =old_put;
Fs->display_doc=old_display;
DocDel(pdoc);
if (pdoc!=ddoc)
DocDel(ddoc);
SettingsPop;
BgtDel;
MenuPop;
}
+132
View File
@@ -0,0 +1,132 @@
#define SFT_GENERIC 1
public U8 **StrFileRead(U8 *name,I64 *_max_num=NULL,
U8 **_colors=NULL,Bool no_nums=FALSE)
{
CDoc *doc=DocRead(name,DOCF_DBL_DOLLARS|DOCF_NO_CURSOR);
CDocEntry *doc_e=doc->head.next;
I64 i,max_num=0;
U8 *ptr,**res,*colors;
while (doc_e!=doc) {
if (doc_e->type_u8==DOCT_TEXT) {
if (no_nums)
i=++max_num;
else {
i=Str2I64(doc_e->tag,,&ptr);
if (i>max_num) max_num=i;
if (*ptr==',') ptr++;
ptr=StrNew(ptr);
Free(doc_e->tag);
doc_e->tag=ptr;
}
doc_e->user_data=i;
}
doc_e=doc_e->next;
}
res=CAlloc(sizeof(U8 *)*(max_num+1));
colors=CAlloc(sizeof(U8)*(max_num+1));
doc_e=doc->head.next;
while (doc_e!=doc) {
if (doc_e->type_u8==DOCT_TEXT && 0<=doc_e->user_data<=max_num) {
res[doc_e->user_data]=doc_e->tag;
doc_e->tag=NULL;
colors[doc_e->user_data]=doc_e->type.u8[1]&15;
}
doc_e=doc_e->next;
}
DocDel(doc);
if (_max_num) *_max_num=max_num;
if (_colors)
*_colors=colors;
else
Free(colors);
return res;
}
public U0 StrFileArrDel(U8 **a,I64 max_num)
{
I64 i;
for (i=0;i<=max_num;i++)
Free(a[i]);
Free(a);
}
public I64 StrFileAdd(U8 *st,I64 *_num,
CHashTable *table,I64 color=COLOR_INVALID)
{
CHashGeneric *tmph;
if (!st) return 0;
if (!(tmph=HashFind(st,table,SFT_GENERIC))) {
tmph=CAlloc(sizeof(CHashGeneric));
tmph->type=SFT_GENERIC;
tmph->str=StrNew(st);
tmph->user_data0=(*_num)++;
HashAdd(tmph,table);
}
if (color!=COLOR_INVALID)
tmph->user_data1=color;
return tmph->user_data0;
}
I64 StrEntriesCompare(CHashGeneric *h1,CHashGeneric *h2)
{
return h1->user_data0-h2->user_data0;
}
public U0 StrFileWrite(U8 *name,CHashTable *table,Bool no_nums=FALSE)
{
I64 i,j,cnt,color=BLACK;
CDoc *doc=DocNew(name);
CHashGeneric *tmph,**a;
if (table) {
cnt=0; //Count Strings
for (i=0;i<=table->mask;i++)
cnt+=LinkedLstCnt(table->body[i]);
a=MAlloc(cnt*sizeof(CHashGeneric *));
j=0; //Load Strings
for (i=0;i<=table->mask;i++) {
tmph=table->body[i];
while (tmph) {
a[j++]=tmph;
tmph=tmph->next;
}
}
QSortI64(a,cnt,&StrEntriesCompare);
for (i=0;i<cnt;i++) {
tmph=a[i];
if (tmph->user_data1&15!=color) {
DocPrint(doc,"$$FG,%d$$",tmph->user_data1&15);
color=tmph->user_data1&15;
}
if (no_nums)
DocPrint(doc,"%s\n",tmph->str);
else
DocPrint(doc,"%d,%s\n",tmph->user_data0,tmph->str);
}
Free(a);
}
doc->flags|=DOCF_NO_CURSOR;
DocWrite(doc);
DocDel(doc);
}
public U0 StrFileDel(CHashTable *table)
{
I64 i;
CHashGeneric *tmph,*tmph1;
if (!table) return;
for (i=0;i<=table->mask;i++) {
tmph=table->body[i];
while (tmph) {
tmph1=tmph->next;
Free(tmph->str);
Free(tmph);
tmph=tmph1;
}
}
Free(table->body);
Free(table);
}
+182
View File
@@ -0,0 +1,182 @@
U0 BgtTemplatePurge(CBgtTemplate *tmpt)
{
CBgtEntry *tmpb,*tmpb1;
tmpb=b_head.next;
while (tmpb!=&b_head) {
tmpb1=tmpb->next;
if (tmpb->template==tmpt) {
QueRem(tmpb);
BgtEntryDel2(tmpb);
Free(tmpb);
}
tmpb=tmpb1;
}
}
U0 BgtTemplateDel(CBgtTemplate *tmpt)
{
BgtTemplatePurge(tmpt);
BgtEntryDel2(&tmpt->b);
Free(tmpt);
}
U0 BgtTemplateExpand(CBgtTemplate *tmpt,Bool periodic_copy=FALSE)
{
CDate d,start,end;
CDateStruct ds;
CBgtEntry *tmpb;
Bool first=TRUE;
start=MyStr2Date(tmpt->start_date);
end =MyStr2Date(tmpt->end_date);
tmpt->b.template=tmpt;
switch (tmpt->type) {
case BT_INTERVAL:
d=start;
while (d<=end) {
if (!first || !periodic_copy) {
tmpb=BgtEntryCopy(&tmpt->b,periodic_copy);
tmpb->date=d;
if (periodic_copy)
tmpb->template=NULL;
else
tmpb->type=BE_TEMPLATE_COPY;
BgtIns(tmpb);
}
d+=tmpt->period*0x100000000;
first=FALSE;
}
break;
case BT_MONTHLY:
Date2Struct(&ds,start);
while (TRUE) {
d=Struct2Date(&ds);
if (d<=end) {
if (!first || !periodic_copy) {
tmpb=BgtEntryCopy(&tmpt->b,periodic_copy);
tmpb->date=d;
if (periodic_copy)
tmpb->template=NULL;
else
tmpb->type=BE_TEMPLATE_COPY;
BgtIns(tmpb);
}
} else
break;
if (++ds.mon>12) {
ds.mon=1;
ds.year++;
}
first=FALSE;
}
break;
case BT_BIMONTHLY:
Date2Struct(&ds,start);
while (TRUE) {
d=Struct2Date(&ds);
if (d<=end) {
if (!first || !periodic_copy) {
tmpb=BgtEntryCopy(&tmpt->b,periodic_copy);
tmpb->date=d;
if (periodic_copy)
tmpb->template=NULL;
else
tmpb->type=BE_TEMPLATE_COPY;
BgtIns(tmpb);
}
} else
break;
ds.mon+=2;
if (ds.mon>12) {
ds.mon-=12;
ds.year++;
}
first=FALSE;
}
break;
case BT_SEMIANNUAL:
Date2Struct(&ds,start);
while (TRUE) {
d=Struct2Date(&ds);
if (d<=end) {
if (!first || !periodic_copy) {
tmpb=BgtEntryCopy(&tmpt->b,periodic_copy);
tmpb->date=d;
if (periodic_copy)
tmpb->template=NULL;
else
tmpb->type=BE_TEMPLATE_COPY;
BgtIns(tmpb);
}
} else
break;
ds.mon+=6;
if (ds.mon>12) {
ds.mon-=12;
ds.year++;
}
first=FALSE;
}
break;
case BT_ANNUAL:
Date2Struct(&ds,start);
while (TRUE) {
d=Struct2Date(&ds);
if (d<=end) {
if (!first || !periodic_copy) {
tmpb=BgtEntryCopy(&tmpt->b,periodic_copy);
tmpb->date=d;
if (periodic_copy)
tmpb->template=NULL;
else
tmpb->type=BE_TEMPLATE_COPY;
BgtIns(tmpb);
}
} else
break;
ds.year++;
first=FALSE;
}
break;
}
}
U0 CBgtTemplatesExpand()
{
CBgtTemplate *tmpt=t_head.next;
while (tmpt!=&t_head) {
BgtTemplateExpand(tmpt);
tmpt=tmpt->next;
}
}
CBgtTemplate *BgtTemplatePmt(CBgtTemplate *dft_t=NULL,CBgtEntry *dft_b=NULL)
{
CBgtTemplate t,*tmpt;
CBgtEntry *tmpb;
MemSet(&t,0,sizeof(CBgtTemplate));
if (dft_t) {
MemCpy(&t.start,&dft_t->start,BT_SIZE);
dft_b=&dft_t->b;
} else {
t.type=BT_INTERVAL;
if (dft_b)
StrPrint(&t.start_date,"%D",dft_b->date);
else
StrCpy(&t.start_date,"[");
StrCpy(&t.end_date,"]");
}
while (TRUE)
if (PopUpForm(&t) && ((t.type==BT_INTERVAL && t.period>0) ||
t.type>BT_INTERVAL)) {
if (tmpb=BgtEntryPmt(dft_b)) {
tmpt=CAlloc(sizeof(CBgtTemplate));
MemCpy(&tmpt->start,&t.start,BT_SIZE);
MemCpy(&tmpt->b,tmpb,sizeof(CBgtEntry));
Free(tmpb);
return tmpt;
}
} else
break;
return NULL;
}
+77
View File
@@ -0,0 +1,77 @@
#define BGT_STRINGS_FILE "~/Budget/Strs.DD.Z"
#define BGT_ACCTS_FILE "~/Budget/Accts.DD.Z"
#define BGT_DATA_FILE "~/Budget/Bgt.DATA.Z"
#define BE_NORMAL 0
#define BE_GAS 1
#define BE_ANNIVERSARY 2
#define BE_PRICE 3
#define BE_TEMPLATE_COPY 4
extern class CBgtTemplate;
class CBgtEntry
{
CBgtEntry *next,*last;
U0 start;
CDate date;
U16 type,flags;
U32 credit_idx,debit_idx,desc_idx;
F64 amount;
U0 end;
U8 *credit,*debit,*desc;
CBgtTemplate *template;
CDocEntry *doc_e;
} b_head;
#define BE_SIZE (offset(CBgtEntry.end)-offset(CBgtEntry.start))
#define BT_NULL 0
#define BT_INTERVAL 1
#define BT_MONTHLY 2
#define BT_BIMONTHLY 3
#define BT_SEMIANNUAL 4
#define BT_ANNUAL 5
DefineLstLoad("ST_BGT_TEMPLATE_TYPES",
"Null\0Interval\0Monthly\0Bimonthly\0Semiannual\0Annual\0");
class CBgtTemplate
{
CBgtTemplate *next,*last;
U0 start;
U16 type fmtstr "$$LS,D=\"ST_BGT_TEMPLATE_TYPES\"$$\n";
U16 flags;
U8 start_date[16] fmtstr "$$DA-P,A=\"Start Date:%s\"$$\n";
U8 end_date[16] fmtstr "$$DA-P,A=\"End Date :%s\"$$\n";
F64 period fmtstr "$$DA,A=\"Period :%8.2f\"$$\n";
U0 end;
CBgtEntry b;
} t_head;
#define BT_SIZE (offset(CBgtTemplate.end)-offset(CBgtTemplate.start))
U8 view_acct[512];
CHashTable *accts_table=NULL;
I64 accts_table_strs=0;
CDate MyStr2Date(U8 *st)
{
CDateStruct ds;
CDate res;
if (st&&*st) {
if (StrOcc(st,'['))
res=b_head.next->date;
else if (StrOcc(st,']'))
res=b_head.last->date;
else
res=Str2Date(st);
} else
res=Now;
Date2Struct(&ds,res);
if (ds.year>2050)
ds.year-=100;
return Struct2Date(&ds);
}
+5
View File
@@ -0,0 +1,5 @@
Cd(__DIR__);;
if (!FileFind("~/Budget",,FUF_JUST_DIRS)) {
MkDir("~/Budget");
Copy("Accts.DD.Z","~/Budget");
}
+12
View File
@@ -0,0 +1,12 @@
#help_index "Finance"
Cd(__DIR__);;
#include "BgtStrs"
#include "Budget"
#include "BgtAccts"
#include "BgtEntry"
#include "BgtTemplate"
#include "BgtFile"
#include "BgtMain"
#help_index ""
+4
View File
@@ -0,0 +1,4 @@
Cd(__DIR__);;
#include "Load"
#include "Install" //Might as well always install
Budget;
+128
View File
@@ -0,0 +1,128 @@
//Makes a mesh ball.
#define VERTICES_NUM 1024
#define TRIS_NUM 1024
class Ball
{
I32 vertex_cnt;
I32 tri_cnt;
CD3I32 v[VERTICES_NUM];
CMeshTri t[TRIS_NUM];
} *b;
class BallDefineStruct
{
F64 radius fmtstr "$$DA-TRM,A=\"Radius :%8.3f\"$$\n";
I64 n_longitude fmtstr "$$DA-TRM,A=\"Longitude Faces:%5d\"$$\n";
I64 n_lattitude fmtstr "$$DA-TRM,A=\"Lattitude Rings:%5d\"$$\n";
};
U0 BDInit(BallDefineStruct *bd)
{
MemSet(bd,0,sizeof(BallDefineStruct));
bd->n_longitude=16;
bd->n_lattitude=8;
bd->radius =20.0;
}
U0 BDCorrect(BallDefineStruct *bd)
{
bd->n_longitude=(bd->n_longitude+1)/2;
bd->n_lattitude=(bd->n_lattitude+1)/2;
}
I64 AddVertex(BallDefineStruct *,I64 x,I64 y,I64 z)
{
I64 i;
for (i=0;i<b->vertex_cnt;i++)
if (b->v[i].x==x && b->v[i].y==y && b->v[i].z==z)
return i;
i=b->vertex_cnt++;
b->v[i].x=x;
b->v[i].y=y;
b->v[i].z=z;
return i;
}
I64 AddTri(BallDefineStruct *,I64 c,I64 n0,I64 n1,I64 n2)
{
I64 res=b->tri_cnt++;
b->t[res].color=c;
b->t[res].nums[0]=n0;
b->t[res].nums[1]=n1;
b->t[res].nums[2]=n2;
return res;
}
U8 *Ball2CSprite()
{
//See $LK,"::/Adam/Gr/GrSpritePlot.HC",A="FL:::/Adam/Gr/GrSpritePlot.HC,1"$ for how CSprite are stored.
U8 *res=MAlloc(sizeof(CSpriteMeshU8s)+
b->vertex_cnt*sizeof(CD3I32)+b->tri_cnt*sizeof(CMeshTri)
+sprite_elem_base_sizes[SPT_END]),
*dst=res;
*dst++ =SPT_MESH;
*dst(I32 *)++ =b->vertex_cnt;
*dst(I32 *)++ =b->tri_cnt;
MemCpy(dst,&b->v,b->vertex_cnt*sizeof(CD3I32));
dst+=b->vertex_cnt*sizeof(CD3I32);
MemCpy(dst,&b->t,b->tri_cnt*sizeof(CMeshTri));
dst+=b->tri_cnt*sizeof(CMeshTri);
*dst++ =SPT_END;
return res;
}
public U8 *BallGen()
{
U8 *res;
I64 i,j,n,m,c,p1,p2,p3,p4;
BallDefineStruct bd1,bd2;
F64 r,r1,r2,z1,z2,d_a1,d_a2;
BDInit(&bd1);
while (TRUE) {
if (!DocForm(&bd1))
return NULL;
MemCpy(&bd2,&bd1,sizeof(BallDefineStruct));
BDCorrect(&bd2);
c=PopUpColorLighting;
if (c<0) return NULL;
b=CAlloc(sizeof(Ball));
r=bd2.radius;
n=bd2.n_lattitude;
m=bd2.n_longitude;
d_a1=2*ã/n/4;
d_a2=2*ã/m/2;
for (j=-n;j<n;j++) {
r1=r*Cos( j *d_a1);
r2=r*Cos((j+1)*d_a1);
z1=r*Sin( j *d_a1);
z2=r*Sin((j+1)*d_a1);
for (i=0;i<m;i++) {
p1=AddVertex(&bd2,r1*Cos((2*i +j)*d_a2),r1*Sin((2*i +j)*d_a2),z1);
p2=AddVertex(&bd2,r1*Cos((2*i+2+j)*d_a2),r1*Sin((2*i+2+j)*d_a2),z1);
p3=AddVertex(&bd2,r2*Cos((2*i+1+j)*d_a2),r2*Sin((2*i+1+j)*d_a2),z2);
p4=AddVertex(&bd2,r2*Cos((2*i+3+j)*d_a2),r2*Sin((2*i+3+j)*d_a2),z2);
AddTri(&bd2,c,p1,p2,p3);
AddTri(&bd2,c,p3,p2,p4);
}
}
res=Ball2CSprite;
"%h7c",'\n';
Sprite(res,"\t\t$$SP,\"<1>\",BI=%d$$");
"%h7c",'\n';
"Vertices:%d\n",b->vertex_cnt;
Free(b);
"Do another";
if (YorN)
Free(res);
else
break;
}
return res;
}
+8
View File
@@ -0,0 +1,8 @@
#help_index "Misc"
Cd(__DIR__);;
#include "ManGen"
#include "BallGen"
#include "Models"
#help_index ""
+320
View File
@@ -0,0 +1,320 @@
//Makes a mesh man.
#define VERTICES_NUM 1024
#define TRIS_NUM 1024
class Man
{
I32 vertex_cnt;
I32 tri_cnt;
CD3I32 v[VERTICES_NUM];
CMeshTri t[TRIS_NUM];
} *m;
class ManDefineStruct
{
F64 head_rad fmtstr
"$$DA-TRM,A=\"Head Radius :%8.3f\"$$\n";
F64 torso_len fmtstr
"$$DA-TRM,A=\"Torso Length :%8.3f\"$$\n";
F64 arm_len fmtstr
"$$DA-TRM,A=\"Arm Length :%8.3f\"$$\n";
F64 hand_len fmtstr
"$$DA-TRM,A=\"Hand Length :%8.3f\"$$\n";
F64 leg_len fmtstr
"$$DA-TRM,A=\"Leg Length :%8.3f\"$$\n";
F64 foot_len fmtstr
"$$DA-TRM,A=\"Foot Length :%8.3f\"$$\n";
F64 torso_width fmtstr
"$$DA-TRM,A=\"Torso Width :%8.3f\"$$\n";
F64 torso_depth fmtstr
"$$DA-TRM,A=\"Torso Depth :%8.3f\"$$\n";
F64 arm_rad fmtstr
"$$DA-TRM,A=\"Arm Radius :%8.3f\"$$\n";
F64 hand_rad fmtstr
"$$DA-TRM,A=\"Hand Radius :%8.3f\"$$\n";
F64 leg_rad fmtstr
"$$DA-TRM,A=\"Leg Radius :%8.3f\"$$\n";
F64 foot_rad fmtstr
"$$DA-TRM,A=\"Foot Radius :%8.3f\"$$\n\n";
F64 r_shoulder_a1 fmtstr
"$$DA-TRM,A=\"R.Shoulder Front/Back Angle:%8.3f\"$$\n";
F64 l_shoulder_a1 fmtstr
"$$DA-TRM,A=\"L.Shoulder Front/Back Angle:%8.3f\"$$\n";
F64 r_hip_a1 fmtstr
"$$DA-TRM,A=\"R.Hip Front/Back Angle :%8.3f\"$$\n";
F64 l_hip_a1 fmtstr
"$$DA-TRM,A=\"L.Hip Front/Back Angle :%8.3f\"$$\n";
F64 r_shoulder_a2 fmtstr
"$$DA-TRM,A=\"R.Shoulder Side Angle :%8.3f\"$$\n";
F64 l_shoulder_a2 fmtstr
"$$DA-TRM,A=\"L.Shoulder Side Angle :%8.3f\"$$\n";
F64 r_hip_a2 fmtstr
"$$DA-TRM,A=\"R.Hip Side Angle :%8.3f\"$$\n";
F64 l_hip_a2 fmtstr
"$$DA-TRM,A=\"L.Hip Side Angle :%8.3f\"$$\n";
F64 r_elbow_a fmtstr
"$$DA-TRM,A=\"R.Elbow Angle :%8.3f\"$$\n";
F64 l_elbow_a fmtstr
"$$DA-TRM,A=\"L.Elbow Angle :%8.3f\"$$\n";
F64 r_knee_a fmtstr
"$$DA-TRM,A=\"R.Knee Angle :%8.3f\"$$\n";
F64 l_knee_a fmtstr
"$$DA-TRM,A=\"L.Knee Angle :%8.3f\"$$\n";
F64 r_wrist_a fmtstr
"$$DA-TRM,A=\"R.Wrist Angle :%8.3f\"$$\n";
F64 l_wrist_a fmtstr
"$$DA-TRM,A=\"L.Wrist Angle :%8.3f\"$$\n";
F64 r_ankle_a fmtstr
"$$DA-TRM,A=\"R.Ankle Angle :%8.3f\"$$\n";
F64 l_ankle_a fmtstr
"$$DA-TRM,A=\"L.Ankle Angle :%8.3f\"$$\n";
};
U0 MDInit(ManDefineStruct *md)
{
MemSet(md,0,sizeof(ManDefineStruct));
md->head_rad =5.0;
md->torso_len =35.0;
md->arm_len =30.0;
md->hand_len =8.0;
md->leg_len =32.0;
md->foot_len =16.0;
md->torso_width=20.0;
md->torso_depth=10.0;
md->arm_rad =3.5;
md->hand_rad =2.0;
md->leg_rad =4.0;
md->foot_rad =3.0;
md->r_shoulder_a1 =30;
md->l_shoulder_a1 =-30;
md->r_hip_a1 =-45;
md->l_hip_a1 =45;
md->r_shoulder_a2 =10;
md->l_shoulder_a2 =10;
md->r_hip_a2 =-5;
md->l_hip_a2 =-5;
md->r_elbow_a =30;
md->l_elbow_a =0;
md->r_knee_a =0;
md->l_knee_a =30;
md->r_wrist_a =0;
md->l_wrist_a =0;
md->r_ankle_a =0;
md->l_ankle_a =0;
}
U0 MDCorrect(ManDefineStruct *md)
{
md->r_ankle_a =-md->r_ankle_a;
md->l_ankle_a =-md->l_ankle_a;
md->r_knee_a =-md->r_knee_a;
md->l_knee_a =-md->l_knee_a;
md->r_hip_a2 =-md->r_hip_a2;
md->r_shoulder_a2=-md->r_shoulder_a2;
md->r_ankle_a+=90;
md->l_ankle_a+=90;
md->foot_len-=md->leg_rad;
md->r_elbow_a+=md->r_shoulder_a1;
md->l_elbow_a+=md->l_shoulder_a1;
md->r_knee_a+=md->r_hip_a1;
md->l_knee_a+=md->l_hip_a1;
md->r_wrist_a+=md->r_elbow_a;
md->l_wrist_a+=md->l_elbow_a;
md->r_ankle_a+=md->r_knee_a;
md->l_ankle_a+=md->l_knee_a;
}
I64 AddVertex(ManDefineStruct *md,I64 x,I64 y,I64 z)
{
I64 res=m->vertex_cnt++;
m->v[res].x=-x;
m->v[res].y=-y-md->leg_len-md->foot_rad*2;
m->v[res].z=-z;
return res;
}
I64 AddTri(ManDefineStruct *,I64 c,I64 n0,I64 n1,I64 n2)
{
I64 res=m->tri_cnt++;
m->t[res].color=c;
m->t[res].nums[0]=n1;
m->t[res].nums[1]=n0;
m->t[res].nums[2]=n2;
return res;
}
U0 AddBox(ManDefineStruct *md,I64 c,I64 x1,I64 y1,I64 z1,
F64 w,F64 h,F64 d,F64 h2,F64 h3,F64 az,F64 ay,F64 ax,
I64 *ox,I64 *oy,I64 *oz)
{
I64 *r;
I64 p1a,p2a,p3a,p4a;
I64 p1b,p2b,p3b,p4b;
I64 wx=w/2,wy=0,wz=0,hx=0,hy=h,hz=0,h2x=0,h2y=h2,h2z=0,
h3x=0,h3y=h3,h3z=0,dx=0,dy=0,dz=d/2;
r=Mat4x4IdentNew;
Mat4x4RotZ(r,az*ã/180.0);
Mat4x4RotY(r,ay*ã/180.0);
Mat4x4RotX(r,ax*ã/180.0);
Mat4x4MulXYZ(r,&wx,&wy,&wz);
Mat4x4MulXYZ(r,&hx,&hy,&hz);
Mat4x4MulXYZ(r,&h2x,&h2y,&h2z);
Mat4x4MulXYZ(r,&h3x,&h3y,&h3z);
Mat4x4MulXYZ(r,&dx,&dy,&dz);
p1a=AddVertex(md,x1+dx -wx+h2x,y1+dy -wy+h2y,z1+dz -wz+h2z);
p2a=AddVertex(md,x1+dx +wx+h2x,y1+dy +wy+h2y,z1+dz +wz+h2z);
p3a=AddVertex(md,x1+dx+hx-wx ,y1+dy+hy-wy ,z1+dz+hz-wz);
p4a=AddVertex(md,x1+dx+hx+wx ,y1+dy+hy+wy ,z1+dz+hz+wz);
AddTri(md,c,p1a,p2a,p3a);
AddTri(md,c,p4a,p3a,p2a);
p1b=AddVertex(md,x1-dx -wx+h2x,y1-dy -wy+h2y,z1-dz -wz+h2z);
p2b=AddVertex(md,x1-dx +wx+h2x,y1-dy +wy+h2y,z1-dz +wz+h2z);
p3b=AddVertex(md,x1-dx+hx-wx ,y1-dy+hy-wy ,z1-dz+hz-wz);
p4b=AddVertex(md,x1-dx+hx+wx ,y1-dy+hy+wy ,z1-dz+hz+wz);
AddTri(md,c,p1b,p2b,p3b);
AddTri(md,c,p4b,p3b,p2b);
AddTri(md,c,p1a,p2a,p1b);
AddTri(md,c,p2b,p1b,p2a);
AddTri(md,c,p3a,p4a,p3b);
AddTri(md,c,p4b,p3b,p4a);
AddTri(md,c,p1a,p3a,p1b);
AddTri(md,c,p3b,p1b,p3a);
AddTri(md,c,p2a,p4a,p2b);
AddTri(md,c,p4b,p2b,p4a);
*ox=x1+hx-h3x;
*oy=y1+hy-h3y;
*oz=z1+hz-h3z;
Free(r);
}
U8 *Man2CSprite()
{
//See $LK,"::/Adam/Gr/GrSpritePlot.HC",A="FL:::/Adam/Gr/GrSpritePlot.HC,1"$ for how CSprite are stored.
U8 *res=MAlloc(sizeof(CSpriteMeshU8s)+
m->vertex_cnt*sizeof(CD3I32)+m->tri_cnt*sizeof(CMeshTri)+
sprite_elem_base_sizes[SPT_END]),
*dst=res;
*dst++ =SPT_MESH;
*dst(I32 *)++ =m->vertex_cnt;
*dst(I32 *)++ =m->tri_cnt;
MemCpy(dst,&m->v,m->vertex_cnt*sizeof(CD3I32));
dst+=m->vertex_cnt*sizeof(CD3I32);
MemCpy(dst,&m->t,m->tri_cnt*sizeof(CMeshTri));
dst+=m->tri_cnt*sizeof(CMeshTri);
*dst++ =SPT_END;
return res;
}
public U8 *ManGen()
{
U8 *res;
I64 x,y,z,c1,c2,c3,c4;
ManDefineStruct md1,md2;
MDInit(&md1);
while (TRUE) {
if (!DocForm(&md1))
return NULL;
MemCpy(&md2,&md1,sizeof(ManDefineStruct));
MDCorrect(&md2);
c1=PopUpColorLighting("$$BK,1$$Shirt$$BK,0$$\n");
if (c1<0) return NULL;
c2=PopUpColorLighting("$$BK,1$$Pants$$BK,0$$\n");
if (c2<0) return NULL;
c3=PopUpColorLighting("$$BK,1$$Skin$$BK,0$$\n");
if (c3<0) return NULL;
c4=PopUpColorLighting("$$BK,1$$Shoes$$BK,0$$\n");
if (c4<0) return NULL;
m=CAlloc(sizeof(Man));
//Head
AddBox(&md2,c3,0,md2.torso_len+md2.head_rad*2,0,
md2.head_rad*2,-md2.head_rad*2,md2.head_rad*2,0,0, 0,0,0,
&x,&y,&z);
//Torso
AddBox(&md2,c1,0,md2.torso_len,0,
md2.torso_width,-md2.torso_len,md2.torso_depth,0,0, 0,0,0,
&x,&y,&z);
//Right Arm
AddBox(&md2,c1,-md2.torso_width/2-md2.arm_rad,md2.torso_len-md2.arm_rad,0,
md2.arm_rad*2,-md2.arm_len/2,md2.arm_rad*2,md2.arm_rad,0,
md2.r_shoulder_a2,0,md2.r_shoulder_a1,&x,&y,&z);
AddBox(&md2,c3,x,y,z,
md2.arm_rad*2,-md2.arm_len/2,md2.arm_rad*2,0,0,
md2.r_shoulder_a2,0,md2.r_elbow_a,&x,&y,&z);
AddBox(&md2,c3,x,y,z,
md2.arm_rad*2,-md2.hand_len,md2.hand_rad*2,0,0,
md2.r_shoulder_a2,0,md2.r_wrist_a,&x,&y,&z);
//Left Arm
AddBox(&md2,c1,md2.torso_width/2+md2.arm_rad,md2.torso_len-md2.arm_rad,0,
md2.arm_rad*2,-md2.arm_len/2,md2.arm_rad*2,md2.arm_rad,0,
md2.l_shoulder_a2,0,md2.l_shoulder_a1,&x,&y,&z);
AddBox(&md2,c3,x,y,z,
md2.arm_rad*2,-md2.arm_len/2,md2.arm_rad*2,0,0,
md2.l_shoulder_a2,0,md2.l_elbow_a,&x,&y,&z);
AddBox(&md2,c3,x,y,z,
md2.arm_rad*2,-md2.hand_len,md2.hand_rad*2,0,0,
md2.l_shoulder_a2,0,md2.l_wrist_a,&x,&y,&z);
//Right Leg
AddBox(&md2,c2,-md2.torso_width/2+md2.leg_rad,0,0,
md2.leg_rad*2,-md2.leg_len/2,md2.leg_rad*2,0,0,
md2.r_hip_a2,0,md2.r_hip_a1,&x,&y,&z);
AddBox(&md2,c3,x,y,z,
md2.leg_rad*2,-md2.leg_len/2,md2.leg_rad*2,0,md2.foot_rad,
md2.r_hip_a2,0,md2.r_knee_a,&x,&y,&z);
AddBox(&md2,c4,x,y,z,
md2.leg_rad*2,-md2.foot_len,md2.foot_rad*2,md2.leg_rad,0,
md2.r_hip_a2,0,md2.r_ankle_a,&x,&y,&z);
//Left Leg
AddBox(&md2,c2,md2.torso_width/2-md2.leg_rad,0,0,
md2.leg_rad*2,-md2.leg_len/2,md2.leg_rad*2,0,0,
md2.l_hip_a2,0,md2.l_hip_a1,&x,&y,&z);
AddBox(&md2,c3,x,y,z,
md2.leg_rad*2,-md2.leg_len/2,md2.leg_rad*2,0,md2.foot_rad,
md2.l_hip_a2,0,md2.l_knee_a,&x,&y,&z);
AddBox(&md2,c4,x,y,z,
md2.leg_rad*2,-md2.foot_len,md2.foot_rad*2,md2.leg_rad,0,
md2.l_hip_a2,0,md2.l_ankle_a,&x,&y,&z);
res=Man2CSprite;
"%h7c",'\n';
Sprite(res,"\t\t$$SP,\"<1>\",BI=%d$$");
"%h7c",'\n';
Free(m);
"Do another";
if (YorN)
Free(res);
else
break;
}
return res;
}
+25
View File
@@ -0,0 +1,25 @@
#define T_MAN 0
#define T_BALL 1
U0 Models()
{
I64 i;
Bool old_form=LBts(&(DocPut)->flags,DOCf_FORM);
DocClear;
"Make a CSprite model. Then, cut-and-Paste it.\n\n";
"$$LM,4$$";
"\n\n$$BT,\"Man\",LE=T_MAN$$\n\n";
"\n\n$$BT,\"Ball\",LE=T_BALL$$\n\n";
"$$LM,0$$";
i=DocMenu(DocPut);
LBEqu(&(DocPut)->flags,DOCf_FORM,old_form);
DocBottom;
switch (i) {
case T_MAN:
ManGen;
break;
case T_BALL:
BallGen;
break;
}
}
+3
View File
@@ -0,0 +1,3 @@
Cd(__DIR__);;
#include "Load"
Models;
File diff suppressed because it is too large. Load diff
+6
View File
@@ -0,0 +1,6 @@
#help_index "Games"
Cd(__DIR__);;
#include "KeepAway"
#help_index ""
+3
View File
@@ -0,0 +1,3 @@
Cd(__DIR__);;
#include "Load"
KeepAway;
+6
View File
@@ -0,0 +1,6 @@
#help_index "Misc"
Cd(__DIR__);;
#include "Logic"
#help_index ""
+592
View File
@@ -0,0 +1,592 @@
#define TABLE_SIZE_MAX 0x10000
I64 output_found,passes,table_size;
U8 *gate_type_table =NULL,
*displayed_design=NULL,
*added_this_pass =NULL;
U16 *input1_table=NULL,
*input2_table=NULL,
*input3_table=NULL;
#define CONNECT_WIDTH 16
#define GATE_WIDTH 37
$ID,6$
$SP,"",BI=1$
$SP,"",BI=2$
$SP,"",BI=3$
$SP,"",BI=4$
$SP,"",BI=5$
$SP,"",BI=6$
$SP,"",BI=7$
$SP,"",BI=8$
$SP,"",BI=9$
$SP,"",BI=10$
$ID,-6$
U8 *gate_type_lst="NULL\0OUTPUT\0INPUT\0"
"NOT\0AND\0OR\0NAND\0NOR\0XOR\0AND3\0OR3\0NAND3\0NOR3\0";
#define GT_NULL 0 //Specifies that table entry has not been filled-in
#define GT_OUTPUT 1 //Specifies the table entry is a desired output
#define GT_INPUT 2 //Specifies that table entry comes from an input signal
#define GT_FIRST_REAL_GATE 3
#define GT_NOT 3
#define GT_AND 4
#define GT_OR 5
#define GT_NAND 6
#define GT_NOR 7
#define GT_XOR 8
#define GT_AND3 9
#define GT_OR3 10
#define GT_NAND3 11
#define GT_NOR3 12
#define GT_ENTRIES_NUM 13
#define SEL_GATES_NUM 128
U8 *imgs[GT_ENTRIES_NUM]={NULL,NULL,NULL,
$IB,"<NOT>",BI=1$,$IB,"<AND>",BI=2$,$IB,"<OR>",BI=3$,$IB,"<NAND>",BI=4$,$IB,"<NOR>",BI=5$,$IB,"<XOR>",BI=6$,$IB,"<AND3>",BI=7$,$IB,"<OR3>",BI=8$,$IB,"<NAND3>",BI=9$,$IB,"<NOR3>",BI=10$};
I64 num_inputs_entered,num_outputs_entered;
I64 num_sel_gates,
sel_gates[SEL_GATES_NUM];
U0 GetGates()
{
I64 i;
U8 *st;
"\nEnter the available gate types in the order you prefer them to be used.\n"
"Your choices are:\n";
for (i=GT_FIRST_REAL_GATE;i<GT_ENTRIES_NUM;i++)
"%z ",i,gate_type_lst;
'\n';
num_sel_gates=0;
while (num_sel_gates<GT_ENTRIES_NUM) {
"%d",num_sel_gates;
st=GetStr(" Gate: ");
if (!*st) {
Free(st);
return;
}
i=LstMatch(st,gate_type_lst,LMF_IGNORE_CASE);
Free(st);
if (i<GT_FIRST_REAL_GATE)
"Invalid response\n";
else
sel_gates[num_sel_gates++]=i;
}
}
U0 Init()
{
I64 i;
do {
table_size=GetI64("\nTable size in hex (3 input=0x100,4=0x10000): ",0);
if (table_size>TABLE_SIZE_MAX)
"Too large\n";
else if (table_size<1) {
"No table specified, aborting.\n";
throw;
}
} while (table_size>TABLE_SIZE_MAX);
gate_type_table =CAlloc(table_size*sizeof(U8));
displayed_design=MAlloc((table_size+7)/8);
added_this_pass =MAlloc((table_size+7)/8);
input1_table =MAlloc(table_size*sizeof(U16));
input2_table =MAlloc(table_size*sizeof(U16));
input3_table =MAlloc(table_size*sizeof(U16));
"\nEnter the hex truth table column values of inputs.\n";
if (table_size<=0x100)
"For example, enter A=0xF0, B=0xCC and C=0xAA.\n";
else
"For example, enter A=0xFF00, B=0xF0F0, C=0xCCCC and D=0xAAAA.\n";
num_inputs_entered=0;
while (TRUE) {
"Input %C: ",'A'+num_inputs_entered;
i=GetI64("",-1);
if (i<0) break;
if (i>table_size)
"Too large\n";
else {
if (gate_type_table[i])
"Duplicate\n";
else {
gate_type_table[i]=GT_INPUT;
input1_table[i]=num_inputs_entered++;
}
}
}
if (!num_inputs_entered) {
"No inputs specified, aborting.\n";
throw;
}
"\nEnter the hex truth table columns values of the outputs.\n";
num_outputs_entered=0;
while (TRUE) {
"Output %C: ",'A'+num_outputs_entered;
i=GetI64("",-1);
if (i<0) break;
if (i>table_size)
"Too large\n";
else {
if (gate_type_table[i]==GT_INPUT)
"To produce this output, connect to input %C\n",
'A'+input1_table[i];
else if (gate_type_table[i]==GT_OUTPUT)
"Duplicate\n";
else {
gate_type_table[i]=GT_OUTPUT;
input1_table[i]=num_outputs_entered++;
}
}
}
if (!num_outputs_entered) {
"No output specified, aborting.\n";
throw;
}
}
U0 DrawDesign(CDC *dc,I64 *_y,I64 output,I64 depth,I64 *_x_out,I64 *_y_out)
{
I64 y=*_y,type=gate_type_table[output],
xx=(passes-depth)*(GATE_WIDTH+CONNECT_WIDTH),yy=y,
x1,y1,x2,y2,x3,y3;
if (_x_out) *_x_out=xx;
if (_y_out) *_y_out=yy;
if (Bt(displayed_design,output) && type!=GT_INPUT) {
dc->color=GREEN;
GrPrint(dc,xx-FONT_WIDTH*3,y-4,"Dup");
y+=10;
} else
switch (type) {
case GT_INPUT:
dc->color=GREEN;
GrPrint(dc,xx-FONT_WIDTH-4,y-4,"%C",'A'+input1_table[output]);
y+=10;
break;
case GT_NOT:
if (!Bt(displayed_design,output)) {
y+=16;
DrawDesign(dc,&y,input1_table[output],depth+1,&x1,&y1);
yy=y1;
dc->color=BLUE;
Sprite3(dc,xx,yy,0,imgs[type]);
dc->color=RED;
GrLine(dc,xx-GATE_WIDTH,yy,x1,y1);
if (_y_out) *_y_out=yy;
}
break;
case GT_AND:
case GT_OR:
case GT_NAND:
case GT_NOR:
case GT_XOR:
if (!Bt(displayed_design,output)) {
y+=24;
DrawDesign(dc,&y,input1_table[output],depth+1,&x1,&y1);
DrawDesign(dc,&y,input2_table[output],depth+1,&x2,&y2);
yy=(y1+y2)/2;
dc->color=BLUE;
Sprite3(dc,xx,yy,0,imgs[type]);
dc->color=RED;
GrLine(dc,xx-GATE_WIDTH,yy-4,x1,y1);
GrLine(dc,xx-GATE_WIDTH,yy+4,x2,y2);
if (_y_out) *_y_out=yy;
}
break;
case GT_AND3:
case GT_OR3:
case GT_NAND3:
case GT_NOR3:
if (!Bt(displayed_design,output)) {
y+=32;
DrawDesign(dc,&y,input1_table[output],depth+1,&x1,&y1);
DrawDesign(dc,&y,input2_table[output],depth+1,&x2,&y2);
DrawDesign(dc,&y,input3_table[output],depth+1,&x3,&y3);
yy=(y1+y2+y3)/3;
dc->color=BLUE;
Sprite3(dc,xx,yy,0,imgs[type]);
dc->color=RED;
GrLine(dc,xx-GATE_WIDTH,yy-8,x1,y1);
GrLine(dc,xx-GATE_WIDTH,yy ,x2,y2);
GrLine(dc,xx-GATE_WIDTH,yy+8,x3,y3);
if (_y_out) *_y_out=yy;
}
break;
}
dc->color=BLACK;
GrPrint(dc,xx,yy+3,"%04X",output);
Bts(displayed_design,output);
if (_y) *_y=y;
}
U0 DrawIt(CTask *,CDC *dc)
{
I64 y=0;
MemSet(displayed_design,0,(table_size+7)/8*sizeof(Bool));
DrawDesign(dc,&y,output_found,0,NULL,NULL);
}
U0 FillNot(Bool *chged,I64 *num_outputs_found)
{
I64 i,j,old_type;
for (i=0;i<table_size;i++)
if (gate_type_table[i]>GT_OUTPUT && !Bt(added_this_pass,i)) {
progress1=i;
j= (~i) & (table_size-1);
old_type=gate_type_table[j];
if (old_type<GT_INPUT) {
gate_type_table[j]=GT_NOT;
input1_table[j]=i;
Bts(added_this_pass,j);
*chged=TRUE;
if (old_type==GT_OUTPUT) {
if (output_found<0) output_found=j;
*num_outputs_found=*num_outputs_found+1;
}
}
}
}
U0 FillAnd(Bool *chged,I64 *num_outputs_found)
{
I64 i,j,k,old_type;
for (i=0;i<table_size;i++)
if (gate_type_table[i]>GT_OUTPUT && !Bt(added_this_pass,i))
for (k=0;k<table_size;k++)
if (gate_type_table[k]>GT_OUTPUT && !Bt(added_this_pass,k)) {
progress1=i;
j= (i & k) & (table_size-1);
old_type=gate_type_table[j];
if (old_type<GT_INPUT) {
gate_type_table[j]=GT_AND;
input1_table[j]=i;
input2_table[j]=k;
Bts(added_this_pass,j);
*chged=TRUE;
if (old_type==GT_OUTPUT) {
if (output_found<0) output_found=j;
*num_outputs_found=*num_outputs_found+1;
}
}
}
}
U0 FillOr(Bool *chged,I64 *num_outputs_found)
{
I64 i,j,k,old_type;
for (i=0;i<table_size;i++)
if (gate_type_table[i]>GT_OUTPUT && !Bt(added_this_pass,i))
for (k=0;k<table_size;k++)
if (gate_type_table[k]>GT_OUTPUT && !Bt(added_this_pass,k)) {
progress1=i;
j= (i | k) & (table_size-1);
old_type=gate_type_table[j];
if (old_type<GT_INPUT) {
gate_type_table[j]=GT_OR;
input1_table[j]=i;
input2_table[j]=k;
Bts(added_this_pass,j);
*chged=TRUE;
if (old_type==GT_OUTPUT) {
if (output_found<0) output_found=j;
*num_outputs_found=*num_outputs_found+1;
}
}
}
}
U0 FillNAnd(Bool *chged,I64 *num_outputs_found)
{
I64 i,j,k,old_type;
for (i=0;i<table_size;i++)
if (gate_type_table[i]>GT_OUTPUT && !Bt(added_this_pass,i))
for (k=0;k<table_size;k++)
if (gate_type_table[k]>GT_OUTPUT && !Bt(added_this_pass,k)) {
progress1=i;
j= (~ (i & k)) & (table_size-1);
old_type=gate_type_table[j];
if (old_type<GT_INPUT) {
gate_type_table[j]=GT_NAND;
input1_table[j]=i;
input2_table[j]=k;
Bts(added_this_pass,j);
*chged=TRUE;
if (old_type==GT_OUTPUT) {
if (output_found<0) output_found=j;
*num_outputs_found=*num_outputs_found+1;
}
}
}
}
U0 FillNOr(Bool *chged,I64 *num_outputs_found)
{
I64 i,j,k,old_type;
for (i=0;i<table_size;i++)
if (gate_type_table[i]>GT_OUTPUT && !Bt(added_this_pass,i))
for (k=0;k<table_size;k++)
if (gate_type_table[k]>GT_OUTPUT && !Bt(added_this_pass,k)) {
progress1=i;
j= (~ (i | k)) & (table_size-1);
old_type=gate_type_table[j];
if (old_type<GT_INPUT) {
gate_type_table[j]=GT_NOR;
input1_table[j]=i;
input2_table[j]=k;
Bts(added_this_pass,j);
*chged=TRUE;
if (old_type==GT_OUTPUT) {
if (output_found<0) output_found=j;
*num_outputs_found=*num_outputs_found+1;
}
}
}
}
U0 FillXor(Bool *chged,I64 *num_outputs_found)
{
I64 i,j,k,old_type;
for (i=0;i<table_size;i++)
if (gate_type_table[i]>GT_OUTPUT && !Bt(added_this_pass,i))
for (k=0;k<table_size;k++)
if (gate_type_table[k]>GT_OUTPUT && !Bt(added_this_pass,k)) {
progress1=i;
j= (i ^ k) & (table_size-1);
old_type=gate_type_table[j];
if (old_type<GT_INPUT) {
gate_type_table[j]=GT_XOR;
input1_table[j]=i;
input2_table[j]=k;
Bts(added_this_pass,j);
*chged=TRUE;
if (old_type==GT_OUTPUT) {
if (output_found<0) output_found=j;
*num_outputs_found=*num_outputs_found+1;
}
}
}
}
U0 FillAnd3(Bool *chged,I64 *num_outputs_found)
{
I64 i,j,k,l,old_type;
for (i=0;i<table_size;i++)
if (gate_type_table[i]>GT_OUTPUT && !Bt(added_this_pass,i))
for (k=0;k<table_size;k++)
if (gate_type_table[k]>GT_OUTPUT && !Bt(added_this_pass,k))
for (l=0;l<table_size;l++)
if (gate_type_table[l]>GT_OUTPUT && !Bt(added_this_pass,l)) {
progress1=i;
j= (i & k & l) & (table_size-1);
old_type=gate_type_table[j];
if (old_type<GT_INPUT) {
gate_type_table[j]=GT_AND3;
input1_table[j]=i;
input2_table[j]=k;
input3_table[j]=l;
Bts(added_this_pass,j);
*chged=TRUE;
if (old_type==GT_OUTPUT) {
if (output_found<0) output_found=j;
*num_outputs_found=*num_outputs_found+1;
}
}
}
}
U0 FillOr3(Bool *chged,I64 *num_outputs_found)
{
I64 i,j,k,l,old_type;
for (i=0;i<table_size;i++)
if (gate_type_table[i]>GT_OUTPUT && !Bt(added_this_pass,i))
for (k=0;k<table_size;k++)
if (gate_type_table[k]>GT_OUTPUT && !Bt(added_this_pass,k))
for (l=0;l<table_size;l++)
if (gate_type_table[l]>GT_OUTPUT && !Bt(added_this_pass,l)) {
progress1=i;
j= (i | k | l) & (table_size-1);
old_type=gate_type_table[j];
if (old_type<GT_INPUT) {
gate_type_table[j]=GT_OR3;
input1_table[j]=i;
input2_table[j]=k;
input3_table[j]=l;
Bts(added_this_pass,j);
*chged=TRUE;
if (old_type==GT_OUTPUT) {
if (output_found<0) output_found=j;
*num_outputs_found=*num_outputs_found+1;
}
}
}
}
U0 FillNAnd3(Bool *chged,I64 *num_outputs_found)
{
I64 i,j,k,l,old_type;
for (i=0;i<table_size;i++)
if (gate_type_table[i]>GT_OUTPUT && !Bt(added_this_pass,i))
for (k=0;k<table_size;k++)
if (gate_type_table[k]>GT_OUTPUT && !Bt(added_this_pass,k))
for (l=0;l<table_size;l++)
if (gate_type_table[l]>GT_OUTPUT && !Bt(added_this_pass,l)) {
progress1=i;
j= (~(i & k & l)) & (table_size-1);
old_type=gate_type_table[j];
if (old_type<GT_INPUT) {
gate_type_table[j]=GT_NAND3;
input1_table[j]=i;
input2_table[j]=k;
input3_table[j]=l;
Bts(added_this_pass,j);
*chged=TRUE;
if (old_type==GT_OUTPUT) {
if (output_found<0) output_found=j;
*num_outputs_found=*num_outputs_found+1;
}
}
}
}
U0 FillNOr3(Bool *chged,I64 *num_outputs_found)
{
I64 i,j,k,l,old_type;
for (i=0;i<table_size;i++)
if (gate_type_table[i]>GT_OUTPUT && !Bt(added_this_pass,i))
for (k=0;k<table_size;k++)
if (gate_type_table[k]>GT_OUTPUT && !Bt(added_this_pass,k))
for (l=0;l<table_size;l++)
if (gate_type_table[l]>GT_OUTPUT && !Bt(added_this_pass,l)) {
progress1=i;
j= (~(i | k | l)) & (table_size-1);
old_type=gate_type_table[j];
if (old_type<GT_INPUT) {
gate_type_table[j]=GT_NOR3;
input1_table[j]=i;
input2_table[j]=k;
input3_table[j]=l;
Bts(added_this_pass,j);
*chged=TRUE;
if (old_type==GT_OUTPUT) {
if (output_found<0) output_found=j;
*num_outputs_found=*num_outputs_found+1;
}
}
}
}
I64 FillGateTable()
{
I64 current_gate,num_outputs_found=0;
Bool chged=TRUE;
passes=1;
output_found=-1;
ProgressBarsRst;
progress1_max=table_size;
'\n';
while (num_outputs_found<num_outputs_entered && chged) {
"Pass : %d\n",passes++;
chged=FALSE;
MemSet(added_this_pass,0,(table_size+7)/8);
for (current_gate=0;current_gate<num_sel_gates &&
num_outputs_found<num_outputs_entered;current_gate++) {
switch (sel_gates[current_gate]) {
case GT_NOT: FillNot (&chged,&num_outputs_found); break;
case GT_AND: FillAnd (&chged,&num_outputs_found); break;
case GT_OR: FillOr (&chged,&num_outputs_found); break;
case GT_NAND: FillNAnd (&chged,&num_outputs_found); break;
case GT_NOR: FillNOr (&chged,&num_outputs_found); break;
case GT_XOR: FillXor (&chged,&num_outputs_found); break;
case GT_AND3: FillAnd3 (&chged,&num_outputs_found); break;
case GT_OR3: FillOr3 (&chged,&num_outputs_found); break;
case GT_NAND3: FillNAnd3(&chged,&num_outputs_found); break;
case GT_NOR3: FillNOr3 (&chged,&num_outputs_found); break;
}
}
}
ProgressBarsRst;
return num_outputs_found;
}
U0 CleanUp()
{
Free(gate_type_table);
Free(displayed_design);
Free(added_this_pass);
Free(input1_table);
Free(input2_table);
Free(input3_table);
}
U0 DigitalLogic()
{
gate_type_table =NULL;
displayed_design=NULL;
added_this_pass =NULL;
input1_table =NULL;
input2_table =NULL;
input3_table =NULL;
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
AutoComplete;
WinBorder(ON);
WinMax;
DocClear;
GetGates;
try {
Init;
if (FillGateTable) {
DocCursor;
DocClear;
Fs->draw_it=&DrawIt;
GetChar;
DocClear;
Refresh(2,TRUE);
DocBottom;
}
} catch
PutExcept;
SettingsPop;
CleanUp;
}
ºÜÿÿÿøÿÿÿ%ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÜÿÿÿøÿÿÿ%ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÜÿÿÿøÿÿÿ%ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâÜÿÿÿ÷ÿÿÿ%ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâÜÿÿÿ÷ÿÿÿ%ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâÜÿÿÿ÷ÿÿÿ%ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿªÜÿÿÿõÿÿÿ&ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿLine truncated
ÒÜÿÿÿôÿÿÿ%ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+3
View File
@@ -0,0 +1,3 @@
Cd(__DIR__);;
#include "Load"
DigitalLogic;
@@ -0,0 +1,24 @@
//9 has words
U0 Song()
{
Fs->task_end_cb=&SndTaskEndCB;
MusicSettingsRst;
music.tempo= 2.480;
music.stacatto_factor= 0.902;
try {
while (!ScanKey) {
Play("5qEsCDCDqCDeEGsE4B5E4B5eC4B5sD4A5D4A",
"Be \0like \0 \0a \0 \0child \0 \0 \0 \0"
"some \0 \0re\0 \0spect.\n\0 \0 \0 \0 \0 \0");
Play("5qEsCDCDqCDeEGsE4B5E4B5eC4B5sD4A5D4A",
"Ma\0tur\0 \0i\0 \0ty \0 \0 \0 \0don't \0 \0"
"ne\0 \0glect.\n\0 \0 \0 \0 \0 \0");
Play("4eB5DqF4sGAGAqAAA5etD4AA5sD4B5D4B");
Play("4eB5DqF4sGAGAqAAA5etD4AA5sD4B5D4B");
}
} catch
PutExcept;
Snd;
}
Song;
Binary file not shown.
Binary file not shown.
+24
View File
@@ -0,0 +1,24 @@
$WW,1$$FG,5$$TX+CX,"Psalmody Help"$$FG$
* The keyboard can be used as an organ by typing letter keys or clicking the mouse on the keyboard diagram$FG$. You can "record" notes by pressing the red bttn and typing letters. They will appear on the musical staff. You can edit and save them.
* The clipboard can be used to cut and paste.
* $FG,2$Psalmody$FG$ uses $LK,"HolyC",A="FI:::/Doc/HolyC.DD"$ files as the song format! See $LK,"::/Apps/Psalmody/Examples/prosper.HC"$. The $FG,2$Psalmody$FG$ program does not fully parse the songs when loading them back in, so changes made outside $FG,2$Psalmody$FG$ will be lost, like if you add graphics.
* The first line of the $LK,"HolyC",A="FI:::/Doc/HolyC.DD"$ song files is a comment with a category recognized by $LK,"JukeBox",A="FF:::/Apps/Psalmody/JukeBox.HC,JukeBox"$(). The categories are $FG,2$"no nothing"$FG$, $FG,2$"has words"$FG$, $FG,2$"has graphics"$FG$, or $FG,2$"special"$FG$. The third character in the song comment is a digit rating number, shown in $LK,"JukeBox",A="FF:::/Apps/Psalmody/JukeBox.HC,JukeBox"$(). You can set the song rating in $LK,"JukeBox",A="FF:::/Apps/Psalmody/JukeBox.HC,JukeBox"$() by pressing $FG,2$0$FG$-$FG,2$9$FG$. You can press $FG,2$<DELETE>$FG$ to delete songs.
* You can take the $LK,"Play",A="MN:Play"$() stmts out of a song file and place them in your programs. You can also add a song to a document with $FG,2$<CTRL-l>$FG$, but you should do it after pressing $FG,2$<CTRL-t>$FG$ because the clipboard-insert in $FG,2$<CTRL-l>$FG$ is screwy. See this $SO,"<Song>",A="4qG5EC4BeGG5qCeFD4sB5G4B5G4qG5EC4BeGG5qCeFD4sB5G4B5GqEeEFqE4BeG5FetC4A5GqFCEeEFqE4BeG5FetC4A5GqFC"$ after pressing $FG,2$<CTRL-t>$FG$, now.
* You can call $LK,"JukeBox",A="FF:::/Apps/Psalmody/JukeBox.HC,JukeBox"$("~/Psalmody"); to play your songs.
* To create a $FG,2$.SND$FG$ file which can be exported and played under Windows, set the $FG,2$Bool$FG$ $LK,"snd.record",A="MN:CSndGlbls"$ to $FG,2$TRUE$FG$, play music, and set it to $FG,2$FALSE$FG$. Then, call $LK,"SndFileCreate",A="MN:SndFileCreate"$(). You might wish to make a $FG,2$<CTRL-ALT-key>$FG$ to toggle this system level recording feat. See $LK,"Snd",A="MN:Snd"$(). Add this code to your $LK,"~/HomeKeyPlugIns.HC"$ file.
$FG,5$U0 CtrlAltR(I64)
{
snd.record=!snd.record;
}
CtrlAltCBSet('R',&CtrlAltR,"Cmd /Toggle snd.record");$FG$
* When calling $LK,"SndFileCreate",A="MN:SndFileCreate"$() you can set a waveform. The PC speaker is $LK,"WF_SQUARE",A="MN:WF_SQUARE"$. You can sel reverb and averaging, also.
+2
View File
@@ -0,0 +1,2 @@
if (!FileFind("~/Psalmody",,FUF_JUST_DIRS))
MkDir("~/Psalmody");
+138
View File
@@ -0,0 +1,138 @@
CTask *SingleSong(U8 *msg,U8 *name)
{
CTask *task=Spawn(&SrvCmdLine,NULL,name,,Fs);
StrCpy(task->task_title,name);
task->title_src=TTS_LOCKED_CONST;
TaskExe(task,Fs,";",1<<JOBf_WAKE_MASTER|1<<JOBf_FREE_ON_COMPLETE);
WinHorz(task->win_left,task->win_left+50,task);
WinVert(2,2+8,task);
TaskExe(task,NULL,msg,1<<JOBf_EXIT_ON_COMPLETE|1<<JOBf_FREE_ON_COMPLETE);
DocPut(task)->max_entries=100;
return task;
}
#define JB_RUN_LEVEL_NULL 0
#define JB_RUN_LEVEL_ONE 1
#define JB_RUN_LEVEL_TWO 2
Bool JBPutKey(CDoc *doc,U8 *,I64 ch,I64 sc)
{//ch=ASCII; sc=scan_code
CDocEntry *doc_ce=doc->cur_entry,*doc_e;
CDirEntry *tmpde;
CDoc *s;
if (!(sc&(SCF_ALT|SCF_CTRL|SCF_SHIFT))
&& doc_ce->type_u8==DOCT_MENU_VAL && doc_ce->left_exp>=0) {
tmpde=doc_ce->left_exp;
if (sc.u8[0]==SC_DELETE ) {
Beep;
Silent;
Del(tmpde->full_name);
Silent(OFF);
} else if ('0'<=ch<='9') {
if (StrLen(doc_ce->tag)>1)
doc_ce->tag[0]=ch;
s=DocRead(tmpde->full_name);
doc_e=s->head.next;
while (doc_e!=s && doc_e->type_u8!=DOCT_TEXT)
doc_e=doc_e->next;
if (doc_e!=s && doc_e->type_u8==DOCT_TEXT && StrLen(doc_e->tag)>=3) {
doc_e->tag[2]=ch;
DocWrite(s);
}
DocDel(s);
return TRUE;
} else if (ch==CH_SPACE||ch==CH_ESC)
tmpde->user_data++; //JB_RUN_LEVEL++
//<SPACE> is followed by <ESC> --> JB_RUN_LEVEL_TWO
//Actual <ESC> just exits --> JB_RUN_LEVEL_ONE
}
return FALSE;
}
public U0 JukeBox(U8 *dirname="~/Psalmody",U8 **_filename=NULL)
{//_filename is for using this as a song-chooser program.
I64 i=0,rating;
U8 *st,*st2;
CDirEntry *tmpde,*tmpde1;
CDoc *doc=DocNew,*s;
CDocEntry *doc_e;
CTask *task=NULL;
if (_filename)
*_filename=NULL;
dirname=StrNew(dirname);
st=MStrPrint("%s/*.HC.Z",dirname);
tmpde=tmpde1=FilesFind(st);
Free(st);
Free(dirname);
doc->user_put_key=&JBPutKey;
DocPrint(doc,
"Key: $$GREEN$$Graphics $$BLUE$$Words $$RED$$No Nothing "
"$$BLACK$$Incomplete $$CYAN$$Special$$FG$$\n\n"
"$$GREEN$$<DELETE>$$FG$$ to delete a song.\n"
"Press a number to rate a song.\n");
while (tmpde) {
if (!(i++%5))
DocPrint(doc,"\n");
if (FileOcc("Play(",tmpde->full_name,"")) {
st=StrNew(tmpde->name);
FileExtRem(st);
s=DocRead(tmpde->full_name);
doc_e=s->head.next;
while (doc_e!=s && doc_e->type_u8!=DOCT_TEXT)
doc_e=doc_e->next;
rating='0';
if (doc_e!=s && doc_e->type_u8==DOCT_TEXT) {
if ('0'<=doc_e->tag[2]<='9')
rating=doc_e->tag[2];
if (StrMatch("incomplete",doc_e->tag))
DocPrint(doc,"$$BLACK$$");
else if (StrMatch("has graphics",doc_e->tag))
DocPrint(doc,"$$GREEN$$");
else if (StrMatch("has words",doc_e->tag))
DocPrint(doc,"$$BLUE$$");
else if (StrMatch("special",doc_e->tag))
DocPrint(doc,"$$CYAN$$");
else if (StrMatch("no nothing",doc_e->tag)) {
DocPrint(doc,"$$RED$$");
if (FileOcc("\\0",tmpde->full_name,"")) {
s->cur_entry=doc_e->next;
s->cur_col=0;
DocEntryDel(s,doc_e);
DocPrint(s,"//0 has words\n");
DocWrite(s);
}
}
DocPrint(doc,"$$MU-UL,\"%c%-8ts\",LE=%d$$ ",rating,st,tmpde);
tmpde->user_data=JB_RUN_LEVEL_NULL;
}
DocDel(s);
Free(st);
}
tmpde=tmpde->next;
}
DocPrint(doc,"\n$$CYAN$$$$MU-UL,\"DONE\",LE=%d$$\n",DOCM_CANCEL);
while (TRUE) {
if (_filename)
tmpde=PopUpMenu(doc,DOF_INTERCEPT_TASK_END);
else
tmpde=PopUpMenu(doc);
if (task)
Kill(task);
if (tmpde<=0) break;
st2=StrNew(tmpde->name);
if (_filename) {
Free(*_filename);
*_filename=StrNew(tmpde->full_name);
}
if (tmpde->user_data==JB_RUN_LEVEL_ONE) break; //<ESC>
tmpde->user_data=JB_RUN_LEVEL_NULL; //Rst from <SPACE>
FileExtRem(st2);
st=MStrPrint("ExeFile(\"%s\");",tmpde->full_name);
MusicSettingsRst;
task=SingleSong(st,st2);
Free(st2);
Free(st);
}
DocDel(doc);
DirTreeDel(tmpde1);
}
+89
View File
@@ -0,0 +1,89 @@
U0 SongPuppet(CTask *task,I64 passes)
{
CDbgInfo *dbg_info;
I64 i,start,end,rip,last_rip;
CHashFun *tmpf=NULL;
for (i=0;i<250 && TaskValidate(task);i++) {
if (tmpf=HashFind("Song",task->hash_table,HTT_FUN))
break;
Sleep(1);
}
if (tmpf && (dbg_info=tmpf->dbg_info)) {
start=dbg_info->body[0];
end =dbg_info->body[dbg_info->max_line+1-dbg_info->min_line];
last_rip=0;
while (TRUE) {
i=0;
while (TaskValidate(task) && (rip=TaskCaller(task,i++))) {
if (start<=rip<end) {
if (rip<last_rip && --passes<=0)
return;
last_rip=rip;
}
}
Sleep(1);
}
}
}
U0 JukeSongPuppet(CTask *juke_task,I64 passes,I64 song_num,U8 *name)
{
Bool found;
CTask *task;
I64 i;
if (FileExtDot(name))
FileExtRem(name);
BirthWait(&juke_task->popup_task);
TaskWait(juke_task->popup_task);
PostMsg(juke_task->popup_task,MSG_KEY_DOWN_UP,0,SC_CURSOR_UP+SCF_CTRL);
TaskWait(juke_task->popup_task);
for (i=0;i<song_num;i++) {
PostMsg(juke_task->popup_task,MSG_KEY_DOWN_UP,0,SC_CURSOR_RIGHT);
TaskWait(juke_task->popup_task);
}
PostMsg(juke_task->popup_task,MSG_KEY_DOWN_UP,CH_SPACE,0);
TaskWait(juke_task->popup_task);
Sleep(500);
found=FALSE;
task=Fs->next_task;
while (task!=Fs) {
if (!StrCmp(task->task_title,name)) {
found=TRUE;
break;
}
task=task->next_task;
}
if (found) {//Position cursor on song title during song
TaskWait(juke_task->popup_task);
PostMsg(juke_task->popup_task,MSG_KEY_DOWN_UP,0,SC_CURSOR_UP+SCF_CTRL);
TaskWait(juke_task->popup_task);
for (i=0;i<song_num;i++) {
PostMsg(juke_task->popup_task,MSG_KEY_DOWN_UP,0,SC_CURSOR_RIGHT);
TaskWait(juke_task->popup_task);
}
SongPuppet(task,passes);
}
Kill(task);
}
public U0 JukeSongsPuppet(U8 *dirname="~/Psalmody",I64 passes=2,
I64 start_song=0,I64 end_song=I64_MAX)
{//Help make music video by puppeting JukeBox task.
I64 i;
CDirEntry *tmpde,*tmpde1;
CTask *juke_task=User("JukeBox(0x%X);\n",dirname);
Cd(dirname);
tmpde1=FilesFind("*",FUF_RECURSE|FUF_JUST_TXT|FUF_JUST_FILES);
for (tmpde=tmpde1,i=0;tmpde && i<start_song;i++)
tmpde=tmpde->next;
for (i=start_song;tmpde && i<end_song;i++) {
JukeSongPuppet(juke_task,passes,i,tmpde->name);
tmpde=tmpde->next;
}
DirTreeDel(tmpde1);
Kill(juke_task);
}
+12
View File
@@ -0,0 +1,12 @@
#help_index "Snd"
Cd(__DIR__);;
#include "JukeBox"
#include "JukePuppet"
#include "Psalmody"
#include "PsalmodyCtrls"
#include "PsalmodyDraw"
#include "PsalmodyFile"
#include "PsalmodyMain"
#help_index ""
+63
View File
@@ -0,0 +1,63 @@
/*$WW,1$
This uses four types of ctrls
1) The pull-down menu.
2) The $LK,"CCtrl",A="MN:CCtrl"$ type for the tempo/stacatto sliders.
3) The active $LK,"CDoc",A="MN:CDoc"$ sprite bttns with macros for left/record/play/right.
4) Hand-made ctrls for the kbdgraphic, notes and staff.
This uses four types of output
1) The $LK,"CDoc",A="MN:CDoc"$ for the text and bttns and kbdgraphic.
2) The Fs->draw_it() for the staff region, drawn every refresh.
3) The gr.dc persistent layer for the note chooser, meter chooser. The persistent layer is used during drag-and-drop.
4) The Fs->next_ctrl for the tempo/stacatto sliders.
See $LK,"GrUpdateTaskWin",A="MN:GrUpdateTaskWin"$(), $LK,"GrUpdateTasks",A="MN:GrUpdateTasks"$() and $LK,"GrUpdateScrn",A="MN:GrUpdateScrn"$().
$WW,1$$WW,0$*/
#define PSMT_HEAD 0
#define PSMT_NOTE 1
#define PSMT_METER 2
#define PSMf_SEL 0
#define PSMF_SEL 1
#define PSMf_SHARP 1
#define PSMf_FLAT 2
#define PSMf_TIE 3
class PsmNote
{
PsmNote *next,*last;
I64 x,y;
U8 *word;
I64 type,flags;
I64 ona,meter_top,meter_bottom;
I64 duration,width;
U8 ascii[32];
};
//Tool types
#define PSMTT_PTR_TOOL 0
#define PSMTT_BOX_TOOL 1
class PsmCtrl
{
PsmNote head;
PsmNote clipboard;
CMenuEntry *incomplete_entry,*record_entry;
I64 scrn_x,tool;
PsmNote *cur_note;
CDC *dc2;
Bool playing;
} psm;
U8 *psm_note_lst="A\0A#\0B\0C\0C#\0D\0D#\0E\0F\0F#\0G\0G#\0";
U8 psm_note_map[12]={6,6,5,4,4,3,3,2,1,1,0,0};
U8 psm_note_inverse_map[7]={10,8,7,5,3,2,0};
+89
View File
@@ -0,0 +1,89 @@
#define TEMPO_SPACING 15
#define TEMPO_RANGE 80
#define TEMPO_BORDER 2
class TempoState
{
I64 tempo,stacatto;
} tempo_state;
U0 DrawTempoCtrl(CDC *dc,CCtrl *c)
{
TempoState *s=c->state;
dc->color=LTGREEN;
GrRect(dc, c->left,c->top,TEMPO_SPACING*3+2,TEMPO_SPACING*2+TEMPO_RANGE);
dc->color=BLACK;
GrRect(dc, c->left+TEMPO_BORDER,c->top+TEMPO_BORDER,
TEMPO_SPACING*3+2-2*TEMPO_BORDER,
TEMPO_SPACING*2+TEMPO_RANGE-2*TEMPO_BORDER);
dc->color=WHITE;
GrLine(dc,c->left+TEMPO_SPACING,c->top+TEMPO_SPACING,
c->left+TEMPO_SPACING,c->top+TEMPO_SPACING+TEMPO_RANGE-1);
GrLine(dc,c->left+2*TEMPO_SPACING+1,c->top+TEMPO_SPACING,
c->left+2*TEMPO_SPACING+1,c->top+TEMPO_SPACING+TEMPO_RANGE-1);
dc->color=LTGREEN;
GrPrint(dc,c->left+TEMPO_SPACING-FONT_WIDTH/2,
c->top+TEMPO_SPACING+TEMPO_RANGE+3,"%d",s->tempo*10/TEMPO_RANGE);
GrPrint(dc,c->left+2*TEMPO_SPACING+1-FONT_WIDTH/2,
c->top+TEMPO_SPACING+TEMPO_RANGE+3,"%d",
s->stacatto*10/TEMPO_RANGE);
GrRect(dc,c->left+TEMPO_SPACING-3,
c->top+TEMPO_SPACING+TEMPO_RANGE-1-s->tempo-2 ,7,5);
GrRect(dc,c->left+2*TEMPO_SPACING+1-3,
c->top+TEMPO_SPACING+TEMPO_RANGE-1-s->stacatto-2,7,5);
dc->color=YELLOW;
GrRect(dc,c->left+TEMPO_SPACING-2,
c->top+TEMPO_SPACING+TEMPO_RANGE-1-s->tempo-1 ,5,3);
GrRect(dc,c->left+2*TEMPO_SPACING+1-2,
c->top+TEMPO_SPACING+TEMPO_RANGE-1-s->stacatto-1,5,3);
dc->color=GREEN;
GrVPrint(dc,c->left+TEMPO_BORDER+2,c->top+TEMPO_SPACING+2,"Tempo");
GrVPrint(dc,c->right-TEMPO_BORDER-2-FONT_WIDTH,
c->top+TEMPO_SPACING+2,"Stacatto");
}
U0 UpdateDerivedTempoCtrl(CCtrl *c)
{
TempoState *s=c->state;
c->right=c->left+TEMPO_SPACING*3+2;
c->bottom=c->top+TEMPO_SPACING*2+TEMPO_RANGE;
s->tempo =ClampI64(s->tempo,0,TEMPO_RANGE-1);
s->stacatto=ClampI64(s->stacatto,0,TEMPO_RANGE-1);
}
U0 LeftClickTempo(CCtrl *c,I64 x,I64 y,Bool)
{
TempoState *s=c->state;
if (x<(c->right+c->left)/2)
s->tempo=TEMPO_RANGE-1-(y-(c->top+TEMPO_SPACING));
else
s->stacatto=TEMPO_RANGE-1-(y-(c->top+TEMPO_SPACING));
if (c->update_derived_vals)
(*c->update_derived_vals)(c);
}
CCtrl *TempoNew()
{
CCtrl *c=CAlloc(sizeof(CCtrl));
c->win_task=Fs;
c->flags=CTRLF_SHOW|CTRLF_CAPTURE_LEFT_MS;
c->type=CTRLT_GENERIC;
c->state=&tempo_state;
c->draw_it=&DrawTempoCtrl;
c->left_click=&LeftClickTempo;
c->update_derived_vals=&UpdateDerivedTempoCtrl;
c->left=396;
c->top=96;
QueIns(c,Fs->last_ctrl);
TaskDerivedValsUpdate;
return c;
}
U0 TempoDel(CCtrl *c)
{
QueRem(c);
Free(c);
}
+589
View File
@@ -0,0 +1,589 @@
$ID,8$
$SP,"<1>",BI=1$
$SP,"<2>",BI=2$
$SP,"<3>",BI=3$
$SP,"<4>",BI=4$
$SP,"<5>",BI=5$
$SP,"<6>",BI=6$
$SP,"<7>",BI=7$
$SP,"<8>",BI=8$
$SP,"<9>",BI=9$
$SP,"<10>",BI=10$
$SP,"<11>",BI=11$
$SP,"<12>",BI=12$
$SP,"<13>",BI=13$
$SP,"<14>",BI=14$
$SP,"<15>",BI=15$
$SP,"<16>",BI=16$
$ID,-8$
#define PSM_NOTE_SPACING 9
#define PSM_DURATIONS_NUM 12
F64 psm_durations[PSM_DURATIONS_NUM+1]={
2*.25/3,.25,2*.5/3,.5,2.0/3.0,0.5*1.5,1.0,1.5,2.0,3.0,4.0,6.0,1000000.0};
U8 *psm_duration_lst="st\0s\0et\0e\0qt\0e.\0q\0q.\0h\0h.\0w\0w.\0";
U8 *psm_duration_imgs[PSM_DURATIONS_NUM]={
$IB,"<1>",BI=1$,$IB,"<1>",BI=1$,$IB,"<2>",BI=2$,$IB,"<2>",BI=2$,$IB,"<3>",BI=3$,$IB,"<2>",BI=2$,$IB,"<3>",BI=3$,$IB,"<3>",BI=3$,$IB,"<4>",BI=4$,$IB,"<4>",BI=4$,$IB,"<5>",BI=5$,$IB,"<5>",BI=5$};
Bool psm_triplet_durations[PSM_DURATIONS_NUM]={TRUE,FALSE,TRUE,
FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE};
Bool PsmBlink()
{
if (Blink || psm.playing)
return TRUE;
else
return FALSE;
}
Bool PsmHasWords(U8 *st)
{
if (st && *st && (StrLen(st)>1 || *st!=CH_SPACE && *st!=CH_SHIFT_SPACE))
return TRUE;
else
return FALSE;
}
Bool PsmIsDotted(I64 duration)
{
U8 *st=LstSub(duration,psm_duration_lst);
if (st[1]=='.')
return TRUE;
else
return FALSE;
}
U0 PsmMarkSel(I64 x1,I64 x2,Bool sel)
{
PsmNote *tmpn=psm.head.next;
while (tmpn!=&psm.head) {
if (sel) {
if (x1<=tmpn->x<=x2)
tmpn->flags|=PSMF_SEL;
} else
tmpn->flags&=~PSMF_SEL;
tmpn=tmpn->next;
}
}
U0 PsmSetWidth(PsmNote *tmpn)
{
if (tmpn->type==PSMT_METER)
tmpn->width=12;
else {
tmpn->width=PSM_NOTE_SPACING;
if (PsmIsDotted(tmpn->duration))
tmpn->width+=PSM_NOTE_SPACING/2;
if (Bt(&tmpn->flags,PSMf_SHARP) || Bt(&tmpn->flags,PSMf_FLAT))
tmpn->width+=PSM_NOTE_SPACING;
}
}
U0 PsmSetOctave(I64 octave)
{
I64 i;
U8 buf[STR_LEN];
CMenuEntry *tmpse;
for (i=1;i<=7;i++) {
StrPrint(buf,"Snd/Octave%d",i);
if (tmpse=MenuEntryFind(Fs->cur_menu,buf)) {
if (i==octave)
tmpse->checked=TRUE;
else
tmpse->checked=FALSE;
}
}
}
U0 DrawNote(CDC *dc,I64 x,I64 y,I64 duration)
{
if (0<=duration<=PSM_DURATIONS_NUM) {
Sprite3(dc,x,y,0,psm_duration_imgs[duration]);
if (psm_triplet_durations[duration])
Sprite3(dc,x,y,0,$IB,"<16>",BI=16$);
if (PsmIsDotted(duration))
Sprite3(dc,x,y,0,$IB,"<15>",BI=15$);
}
}
U0 DrawTimeSignature(CDC *dc,I64 x,I64 y,I64 top,I64 bottom)
{
GrPrint(dc,x,y,"%d",top);
GrPrint(dc,x,y+FONT_HEIGHT,"%d",bottom);
}
U0 PsmRecalcNoteXY()
{
F64 measure_len=4,measure_left=measure_len;
PsmNote *tmpn=psm.head.next;
I64 x=8-psm.scrn_x,ona,note,octave;
while (TRUE) {
tmpn->x=x;
tmpn->y=50;
if (tmpn==&psm.head)
break;
else {
if (tmpn->type!=PSMT_METER) {
if (tmpn->ona!=ONA_REST) {
ona=tmpn->ona;
if (Bt(&tmpn->flags,PSMf_SHARP))
ona--;
if (Bt(&tmpn->flags,PSMf_FLAT))
ona++;
octave=Ona2Octave(ona);
note =Ona2Note (ona);
note=music.note_map[*LstSub(note,psm_note_lst)-'A'];
if (note<3)
octave++;
tmpn->y=(15+(psm_note_map[note]-7*(octave-4)))*4;
}
}
x+=tmpn->width;
if (tmpn->type==PSMT_METER) {
measure_len=tmpn->meter_top*4.0/tmpn->meter_bottom;
measure_left=0;
} else
measure_left-=psm_durations[tmpn->duration];
if (measure_left<0.001) {
x+=PSM_NOTE_SPACING;
measure_left=measure_len;
}
}
tmpn=tmpn->next;
}
}
U0 DrawIt(CTask *task,CDC *dc)
{
PsmNote *tmpn;
I64 i,x,y,
w=task->pix_width;
F64 measure_len=4,measure_left=measure_len;
dc->color=BLACK;
for (i=1;i<6;i++)
GrLine(dc,0,i*8,w,i*8);
for (i=7;i<12;i++)
GrLine(dc,0,i*8,w,i*8);
PsmRecalcNoteXY;
if (psm.cur_note->x<64) {
psm.scrn_x-=128;
PsmRecalcNoteXY;
}
if (psm.cur_note->x>=GR_WIDTH-64) {
psm.scrn_x+=128;
PsmRecalcNoteXY;
}
tmpn=psm.head.next;
while (tmpn!=&psm.head) {
x=tmpn->x;
y=tmpn->y;
if (measure_left<0.001) {
dc->color=BLACK;
GrLine(dc,x-PSM_NOTE_SPACING,8,x-PSM_NOTE_SPACING,11*8);
measure_left=measure_len;
}
if (tmpn->type==PSMT_METER) {
if (tmpn==psm.cur_note && PsmBlink)
dc->color=BROWN;
else
dc->color=BLACK;
DrawTimeSignature(dc,x,5*8,tmpn->meter_top,tmpn->meter_bottom);
measure_len=tmpn->meter_top*4.0/tmpn->meter_bottom;
measure_left=0;
} else {
if (tmpn==psm.cur_note && PsmBlink) {
dc->color=BROWN;
GrPrint(dc,x+8,y,"%s",tmpn->word);
} else if (tmpn->flags&PSMF_SEL)
dc->color=RED;
else {
if (tmpn->ona!=ONA_REST)
dc->color=BLACK;
else
dc->color=LTGRAY;
if (PsmHasWords(tmpn->word))
dc->color=GREEN;
}
DrawNote(dc,x,y,tmpn->duration);
if (PsmIsDotted(tmpn->duration))
x+=PSM_NOTE_SPACING/2;
if (Bt(&tmpn->flags,PSMf_SHARP))
Sprite3(dc,x,y,0,$IB,"<13>",BI=13$);
else if (Bt(&tmpn->flags,PSMf_FLAT))
Sprite3(dc,x,y,0,$IB,"<14>",BI=14$);
measure_left-=psm_durations[tmpn->duration];
}
tmpn=tmpn->next;
}
if (psm.cur_note==&psm.head && PsmBlink)
dc->color=BROWN;
else
dc->color=BLACK;
Sprite3(dc,psm.head.x,50,0,$IB,"<12>",BI=12$);
}
#define PSM_NOTE_BOX_X 220
#define PSM_NOTE_BOX_Y (13*FONT_HEIGHT+14)
U0 PsmSetPickNoteBoxX(I64 duration,I64 *x)
{
I64 i;
*x=PSM_NOTE_BOX_X;
for (i=0;i<duration;i++) {
if (PsmIsDotted(i))
*x+=PSM_NOTE_SPACING/2;
*x+=PSM_NOTE_SPACING+4;
}
}
I64 PsmGetPickNoteBoxDuration(I64 xx,I64 yy)
{
I64 i,x1,x2;
if (PSM_NOTE_BOX_Y-14<=yy<PSM_NOTE_BOX_Y+6) {
for (i=0;i<PSM_DURATIONS_NUM;i++) {
PsmSetPickNoteBoxX(i,&x1);
PsmSetPickNoteBoxX(i+1,&x2);
if (x1<=xx+PSM_NOTE_SPACING/2<x2)
return i;
}
}
return -1;
}
U0 DrawPickNoteBox()
{
I64 i,x;
for (i=0;i<PSM_DURATIONS_NUM;i++) {
PsmSetPickNoteBoxX(i,&x);
if (PsmIsDotted(i))
psm.dc2->color=RED;
else if (psm_triplet_durations[i])
psm.dc2->color=LTRED;
else
psm.dc2->color=BLACK;
DrawNote(psm.dc2,x,PSM_NOTE_BOX_Y,i);
}
}
#define PSM_TOOLS_X 450
#define PSM_TOOLS_Y 13*FONT_HEIGHT
U0 DrawPickTools()
{
if (psm.tool==PSMTT_BOX_TOOL)
psm.dc2->color=ROPF_DITHER+WHITE<<16+RED;
else
psm.dc2->color=ROPF_DITHER+WHITE<<16+BLACK;
GrBorder(psm.dc2,PSM_TOOLS_X,PSM_TOOLS_Y,PSM_TOOLS_X+10,PSM_TOOLS_Y+10);
if (psm.tool==PSMTT_PTR_TOOL)
psm.dc2->color=RED;
else
psm.dc2->color=BLACK;
(*gr.fp_draw_ms)(psm.dc2,PSM_TOOLS_X+15,PSM_TOOLS_Y);
psm.dc2->color=BLACK;
}
Bool PsmGetPickToolBox(I64 xx,I64 yy)
{
if (PSM_TOOLS_X<=xx<PSM_TOOLS_X+27 && PSM_TOOLS_Y<=yy<PSM_TOOLS_Y+15) {
PsmMarkSel(0,0,FALSE);
if (xx<PSM_TOOLS_X+13)
psm.tool=PSMTT_BOX_TOOL;
else
psm.tool=PSMTT_PTR_TOOL;
return TRUE;
} else
return FALSE;
}
#define PSM_METERS_NUM 7
I64 meter_tops[PSM_METERS_NUM] ={2,3,4,5,6,7,9},
meter_bottoms[PSM_METERS_NUM]={4,4,4,4,8,8,8};
#define PSM_METER_X 485
#define PSM_METER_Y 13*FONT_HEIGHT
#define PSM_METER_W 12
Bool PsmGetPickMeterBox(I64 xx,I64 yy,I64 *top,I64 *bottom)
{
I64 i;
if (PSM_METER_X<=xx<PSM_METER_X+PSM_METER_W*PSM_METERS_NUM &&
PSM_METER_Y<=yy<PSM_METER_Y+2*FONT_HEIGHT) {
i=(xx-PSM_METER_X)/PSM_METER_W;
*top=meter_tops[i];
*bottom=meter_bottoms[i];
return TRUE;
} else
return FALSE;
}
U0 DrawPickMeterBox()
{
I64 i;
psm.dc2->color=BLACK;
for (i=0;i<PSM_METERS_NUM;i++)
DrawTimeSignature(psm.dc2,PSM_METER_X+i*PSM_METER_W,PSM_METER_Y,
meter_tops[i],meter_bottoms[i]);
}
U0 DrawDC2()
{
DCFill;
DrawPickNoteBox;
DrawPickMeterBox;
DrawPickTools;
}
$SP,"<17>",BI=17$
U0 PsmMenu(I64 psm_octave)
{
DocClear;
"$$BG,WHITE$$$$FD,GREEN$$$$CM,0,12$$\n";
Sprite($IB,"<17>",BI=17$);
'\n\n\n\n\n';
DrawDC2;
"$$LTGREEN$$<SPACE>$$FG$$\t\tRest\n"
"$$LTGREEN$$<BACKSPACE>$$FG$$\tDeletes Last Note\n"
"$$LTGREEN$$Left Mouse$$FG$$\tDrag note or shift word\n"
"$$LTGREEN$$Right Mouse$$FG$$\tChange duration or set word\n";
Sprite($IB,"<6>",BI=6$,"$$SP+LIS,\"\","
"LM=\"Msg(MSG_KEY_DOWN,0,SCF_CTRL|SC_CURSOR_LEFT);\",BI=%d$$");
" ";
if (psm.playing)
Sprite($IB,"<9>",BI=9$,"$$SP,\"\",LM=\"x\",BI=%d$$");
else
Sprite($IB,"<8>",BI=8$,"$$SP,\"\",LM=\"x\",BI=%d$$");
" ";
if (psm.record_entry->checked) {
psm.record_entry->checked=TRUE;
Sprite($IB,"<10>",BI=10$,"$$SP,\"\",LM=\"z\",BI=%d$$");
} else
Sprite($IB,"<11>",BI=11$,"$$SP,\"\",LM=\"z\",BI=%d$$");
" ";
Sprite($IB,"<7>",BI=7$,"$$SP+LIS,\"\","
"LM=\"Msg(MSG_KEY_DOWN,0,SCF_CTRL|SC_CURSOR_RIGHT);\",BI=%d$$");
"$$CM+LX,0,6$$";
PsmSetOctave(psm_octave);
Refresh(2);
}
"
òÿÿÿñÿÿÿ
ñÿÿÿ
ñÿÿÿ
õÿÿÿ
õÿÿÿ
óÿÿÿ òÿÿÿ
öÿÿÿ
÷ÿÿÿ
ÿÿÿÿýÿÿÿüÿÿÿ
üÿÿÿ
ÿÿÿÿ
ÿÿÿÿýÿÿÿ
òÿÿÿ
þÿÿÿÿÿÿÿÿÿÿÿ
ýÿÿÿ
ÿÿÿÿ
ýÿÿÿ
ýÿÿÿÿÿÿÿ

þÿÿÿÿÿÿÿÿÿÿÿ
óÿÿÿ
óÿÿÿ
óÿÿÿóÿÿÿ
òÿÿÿ òÿÿÿ
ÿÿÿÿýÿÿÿüÿÿÿ
üÿÿÿ
ÿÿÿÿ
ÿÿÿÿýÿÿÿ
òÿÿÿ
þÿÿÿÿÿÿÿÿÿÿÿ
ýÿÿÿ
ÿÿÿÿ
ýÿÿÿ
ýÿÿÿÿÿÿÿ

þÿÿÿÿÿÿÿÿÿÿÿÍ
ÿÿÿÿýÿÿÿüÿÿÿ
üÿÿÿ
ÿÿÿÿ
ÿÿÿÿýÿÿÿ
òÿÿÿ
þÿÿÿÿÿÿÿÿÿÿÿ
ýÿÿÿ
ÿÿÿÿ
ýÿÿÿ
ýÿÿÿÿÿÿÿ

þÿÿÿÿÿÿÿÿÿÿÿV
ÿÿÿÿýÿÿÿüÿÿÿ
üÿÿÿ
ÿÿÿÿ
ÿÿÿÿýÿÿÿ
òÿÿÿE
ÿÿÿÿýÿÿÿüÿÿÿ
üÿÿÿ
ÿÿÿÿ
ÿÿÿÿýÿÿÿa
 


 a
 

 
 Õ
 






   

␍      

  











 








?
 

#
þÿÿÿÖÿÿÿþÿÿÿ&
Öÿÿÿ&␍E
úÿÿÿ
úÿÿÿ

ýÿÿÿ
V
ýÿÿÿ


␍
␍

E
þÿÿÿöÿÿÿöÿÿÿ
öÿÿÿòÿÿÿ
òÿÿÿþÿÿÿòÿÿÿ
ôÿÿÿÿÿÿÿôÿÿÿò
$
$
0$0
,4
44
,,
@$@
<D
DD
<<
|„
„„
||
lt
tt
ll
$À$


ÄA$S4DDFTGdHtJ„K”L¤;´',E<RLTlU|IœP¬[¼]
PP
LT
TT
LL
`$`
p$p
€$€
�$�
 $ 
°$°
À$À
œ¤
¤¤
œœ
¬´
´´
¬¬
¼Ä
ÄÄ
¼¼
P$P0@Pp€ °À@
~  
P
 
␍␍

+427
View File
@@ -0,0 +1,427 @@
U0 PsmNoteDel(PsmNote *tmpn)
{
Free(tmpn->word);
Free(tmpn);
}
PsmNote *PsmNoteCopy(PsmNote *tmpn)
{
PsmNote *tmpn1=MAllocIdent(tmpn);
if (tmpn->word)
tmpn1->word=StrNew(tmpn->word);
else
tmpn1->word=NULL;
return tmpn1;
}
U0 PsmSongDel(PsmNote *head)
{
PsmNote *tmpn,*tmpn1;
tmpn=head->next;
while (tmpn!=head) {
tmpn1=tmpn->next;
PsmNoteDel(tmpn);
tmpn=tmpn1;
}
QueInit(head);
}
U0 PsmCutToClipboard()
{
PsmNote *tmpn,*tmpn1;
PsmSongDel(&psm.clipboard);
tmpn=psm.head.next;
while (tmpn!=&psm.head) {
tmpn1=tmpn->next;
if (tmpn->flags&PSMF_SEL) {
if (psm.cur_note==tmpn)
psm.cur_note=tmpn->next;
QueRem(tmpn);
tmpn->flags&=~PSMF_SEL;
QueIns(tmpn,psm.clipboard.last);
}
tmpn=tmpn1;
}
}
U0 PsmPasteClipboard()
{
PsmNote *tmpn,*tmpn1;
tmpn=psm.clipboard.next;
while (tmpn!=&psm.clipboard) {
tmpn1=PsmNoteCopy(tmpn);
QueIns(tmpn1,psm.cur_note->last);
tmpn=tmpn->next;
}
}
U0 PsmCopyToClipboard()
{
PsmNote *tmpn,*tmpn1;
PsmSongDel(&psm.clipboard);
tmpn=psm.head.next;
while (tmpn!=&psm.head) {
if (tmpn->flags&PSMF_SEL) {
tmpn->flags&=~PSMF_SEL;
tmpn1=PsmNoteCopy(tmpn);
QueIns(tmpn1,psm.clipboard.last);
}
tmpn=tmpn->next;
}
}
PsmNote *PsmFindNote(I64 x,I64)
{
PsmNote *tmpn=psm.head.next;
PsmRecalcNoteXY;
x+=PSM_NOTE_SPACING/2;
while (x>tmpn->next->x && tmpn!=&psm.head)
tmpn=tmpn->next;
return tmpn;
}
U8 *PsmMusicSetOctave(U8 *st,I64 *psm_octave)
{
while ('0'<=*st<='9')
*psm_octave=*st++ -'0';
return st;
}
U8 *PsmMusicSetNoteLen(U8 *st,F64 *psm_duration)
{
Bool cont=TRUE;
do {
switch (*st++) {
case 'w': *psm_duration=4.0; break;
case 'h': *psm_duration=2.0; break;
case 'q': *psm_duration=1.0; break;
case 'e': *psm_duration=0.5; break;
case 's': *psm_duration=0.25; break;
case 't': *psm_duration=2.0* *psm_duration/3.0; break;
case '.': *psm_duration=1.5* *psm_duration; break;
default:
st--;
cont=FALSE;
}
} while (cont);
return st;
}
U0 PsmLoadSongStr(U8 *st,I64 *psm_octave,F64 *psm_duration)
{
PsmNote *tmpn,*tmpn1;
I64 note,i=0;
while (*st) {
tmpn=CAlloc(sizeof(PsmNote));
while (*st && !('A'<=*st<='G') && *st!='R') {
if (*st=='M') {
tmpn1=CAlloc(sizeof(PsmNote));
tmpn1->type=PSMT_METER;
st++;
if ('1'<=*st<='9')
tmpn1->meter_top=*st++-'0';
else
tmpn1->meter_top=4;
if (*st=='/')
st++;
if ('1'<=*st<='9')
tmpn1->meter_bottom=*st++-'0';
else
tmpn1->meter_bottom=4;
PsmSetWidth(tmpn1);
QueIns(tmpn1,psm.head.last);
}
while (*st=='(') {
Bts(&tmpn->flags,PSMf_TIE);
st++;
}
st=PsmMusicSetOctave(st,psm_octave);
st=PsmMusicSetNoteLen(st,psm_duration);
}
if (!*st) {
PsmNoteDel(tmpn);
break;
}
note=*st++-'A';
if (note<7) {
note=music.note_map[note];
if (*st=='b') {
Bts(&tmpn->flags,PSMf_FLAT);
note--;
st++;
if (note<0) //Ab
note=11;
else if (note==2) //Cb
*psm_octave-=1;
} else if (*st=='#') {
Bts(&tmpn->flags,PSMf_SHARP);
note++;
st++;
if (note>11) //G#
note=0;
else if (note==3) //B#
*psm_octave+=1;
}
tmpn->ona=Note2Ona(note,*psm_octave);
} else
tmpn->ona=ONA_REST;
if (*psm_duration<=2*.25/3)
i=0;
else if (*psm_duration<=.25)
i=1;
else if (*psm_duration<=2*.5/3)
i=2;
else if (*psm_duration<=.5)
i=3;
else if (*psm_duration<=2.0/3)
i=4;
else if (*psm_duration<=.5*1.5)
i=5;
else if (*psm_duration<=1.0)
i=6;
else if (*psm_duration<=1.5)
i=7;
else if (*psm_duration<=2.0)
i=8;
else if (*psm_duration<=3.0)
i=9;
else if (*psm_duration<=4.0)
i=10;
else
i=11;
tmpn->duration=i;
tmpn->type=PSMT_NOTE;
PsmSetWidth(tmpn);
QueIns(tmpn,psm.cur_note->last);
}
}
U0 PsmLoadSong(U8 *filename,I64 *psm_octave,F64 *psm_duration)
{
U8 *st;
PsmNote *tmpn;
CCmpCtrl *cc=CmpCtrlNew(MStrPrint("#include \"%s\"",filename));
if (FileOcc("incomplete",filename,""))
psm.incomplete_entry->checked=TRUE;
else
psm.incomplete_entry->checked=FALSE;
while (Lex(cc)) {
if (cc->token==TK_IDENT)
if (!StrCmp(cc->cur_str,"Play")) {
if (Lex(cc)=='(')
if (Lex(cc)==TK_STR) {
tmpn=psm.head.last;
st=LexExtStr(cc);
PsmLoadSongStr(st,psm_octave,psm_duration);
if (cc->token==',') {
if (Lex(cc)==TK_STR) {
st=LexExtStr(cc);
do {
do tmpn=tmpn->next;
while (tmpn!=&psm.head && tmpn->type==PSMT_METER);
if (tmpn!=&psm.head)
tmpn->word=StrNew(st);
st+=StrLen(st)+1;
} while (*st);
}
}
}
} else if (!StrCmp(cc->cur_str,"music") &&
Lex(cc)=='.' && Lex(cc)==TK_IDENT) {
if (!StrCmp(cc->cur_str,"tempo")) {
if (Lex(cc)=='=' && Lex(cc)==TK_F64) {
music.tempo=cc->cur_f64-0.0005;
tempo_state.tempo=Round(TEMPO_RANGE*(music.tempo-0.5)/4.4);
}
} else if (!StrCmp(cc->cur_str,"stacatto_factor")) {
if (Lex(cc)=='=' && Lex(cc)==TK_F64) {
music.stacatto_factor=cc->cur_f64-0.0005;
tempo_state.stacatto=
Round(TEMPO_RANGE*(music.stacatto_factor-0.12)/0.88);
}
}
}
}
CmpCtrlDel(cc);
}
U8 *PsmCvtSong()
{
PsmNote *tmpn;
U8 *st,*src,*dst;
I64 i,ona,note,octave,last_octave,last_duration;
i=0;
tmpn=psm.head.next;
last_octave=I64_MIN;
last_duration=-1;
while (tmpn!=&psm.head) {
dst=&tmpn->ascii;
if (tmpn->type==PSMT_METER) {
*dst++='M';
*dst++=tmpn->meter_top+'0';
*dst++='/';
*dst++=tmpn->meter_bottom+'0';
} else {
if (tmpn->ona!=ONA_REST) {
ona=tmpn->ona;
if (Bt(&tmpn->flags,PSMf_SHARP))
ona--;
if (Bt(&tmpn->flags,PSMf_FLAT))
ona++;
octave=Ona2Octave(ona);
note =Ona2Note (ona);
note=music.note_map[*LstSub(note,psm_note_lst)-'A'];
}
if (Bt(&tmpn->flags,PSMf_TIE))
*dst++='(';
if (octave!=last_octave && tmpn->ona!=ONA_REST) {
*dst++=octave+'0';
last_octave=octave;
}
if (tmpn->duration!=last_duration) {
src=LstSub(tmpn->duration,psm_duration_lst);
*dst++=src[0];
if (src[1])
*dst++=src[1];
last_duration=tmpn->duration;
}
if (tmpn->ona!=ONA_REST) {
src=LstSub(note,psm_note_lst);
*dst++=src[0];
if (src[1])
*dst++=src[1];
else if (Bt(&tmpn->flags,PSMf_FLAT))
*dst++='b';
else if (Bt(&tmpn->flags,PSMf_SHARP))
*dst++='#';
} else
*dst++='R';
}
*dst++=0;
i+=StrLen(tmpn->ascii);
tmpn=tmpn->next;
}
st=MAlloc(i+1);
dst=st;
tmpn=psm.head.next;
while (tmpn!=&psm.head) {
StrCpy(dst,tmpn->ascii);
dst+=StrLen(tmpn->ascii);
tmpn=tmpn->next;
}
*dst++=0;
return st;
}
U8 *PsmSaveSong(U8 *dirname,U8 *full_filename)
{
CDoc *doc=DocNew(full_filename);
Bool has_words;
PsmNote *tmpn,*tmpn1;
F64 measure_len=4,two_measure_left=2*measure_len;
I64 ch;
U8 *ptr;
Free(PsmCvtSong); //set tmpn->ascii;
music.tempo=4.4*tempo_state.tempo/TEMPO_RANGE+0.5;
music.stacatto_factor=0.88*tempo_state.stacatto/TEMPO_RANGE+0.12;
has_words=FALSE;
tmpn=psm.head.next;
while (tmpn!=&psm.head) {
if (PsmHasWords(tmpn->word)) has_words=TRUE;
tmpn=tmpn->next;
}
if (psm.incomplete_entry->checked)
DocPrint(doc,"//0 incomplete\n");
else if (has_words)
DocPrint(doc,"//0 has words\n");
else
DocPrint(doc,"//0 no nothing\n");
DocPrint(doc,
"U0 Song()\n"
"{\n"
" Fs->task_end_cb=&SndTaskEndCB;\n"
" MusicSettingsRst;\n"
" music.tempo=%6.3f;\n"
" music.stacatto_factor=%6.3f;\n"
" try {\n"
" while (!ScanKey) {\n"
"\tPlay(\"",music.tempo+0.0005,music.stacatto_factor+0.0005);
tmpn=psm.head.next;
tmpn1=tmpn;
has_words=FALSE;
while (tmpn!=&psm.head) {
DocPrint(doc,"%s",tmpn->ascii);
if (PsmHasWords(tmpn->word)) has_words=TRUE;
if (tmpn->type==PSMT_METER) {
measure_len=tmpn->meter_top*4.0/tmpn->meter_bottom;
two_measure_left=0;
} else
two_measure_left-=psm_durations[tmpn->duration];
tmpn=tmpn->next;
if (two_measure_left<0.001 && tmpn!=&psm.head) {
if (has_words) {
DocPrint(doc,"\",\n\t\t\"");
while (tmpn1!=tmpn) {
if (tmpn1->type!=PSMT_METER) {
if (ptr=tmpn1->word) {
while (ch=*ptr) {
if (ch==CH_SPACE)
*ptr=CH_SHIFT_SPACE;
ptr++;
}
DocPrint(doc,"%Q\\0",tmpn1->word);
} else
DocPrint(doc,"%c\\0",CH_SHIFT_SPACE);
}
tmpn1=tmpn1->next;
}
}
DocPrint(doc,"\");\n"
"\tPlay(\"");
two_measure_left=2*measure_len;
tmpn1=tmpn;
has_words=FALSE;
}
}
if (has_words) {
DocPrint(doc,"\",\n\t\t\"");
while (tmpn1!=tmpn) {
if (tmpn1->type!=PSMT_METER) {
if (ptr=tmpn1->word) {
while (ch=*ptr) {
if (ch==CH_SPACE)
*ptr=CH_SHIFT_SPACE;
ptr++;
}
DocPrint(doc,"%Q\\0",tmpn1->word);
} else
DocPrint(doc,"%c\\0",CH_SHIFT_SPACE);
}
tmpn1=tmpn1->next;
}
}
DocPrint(doc,"\");\n"
" }\n"
" } catch\n"
" PutExcept;\n"
" Snd;\n"
"}\n"
"\n"
"Song;\n");
DocRecalc(doc);
if (full_filename)
Free(full_filename);
else
StrPrint(doc->filename.name,"%s/Tmp.HC.Z",dirname);
DocWrite(doc,TRUE);
full_filename=StrNew(doc->filename.name);
DocDel(doc);
return full_filename;
}
+798
View File
@@ -0,0 +1,798 @@
#define PSMR_FLAT -8
#define PSMR_SHARP -7
#define PSMR_TIE -6
#define PSMR_REST -5
#define PSMR_INS_NOTE -4
#define PSMR_DELETE_NOTE -3
#define PSMR_SET_WORD -2
F64 PopUpDuration()
{
I64 i;
CDoc *doc=DocNew;
DocPrint(doc,"$$GREEN$$$$MU,\"Set Word\",LE=PSMR_SET_WORD$$\n"
"$$MU,\"Toggle Sharp\",LE=PSMR_SHARP$$\n"
"$$MU,\"Toggle Flat\",LE=PSMR_FLAT$$\n"
"$$MU,\"Toggle Tie\",LE=PSMR_TIE$$\n"
"$$MU,\"Make Rest\",LE=PSMR_REST$$\n"
"$$MU,\"Insert Note\",LE=PSMR_INS_NOTE$$\n"
"$$MU,\"Delete Note\",LE=PSMR_DELETE_NOTE$$\n\n");
for (i=0;i<PSM_DURATIONS_NUM;i++)
DocPrint(doc,"$$MU,\"%7.5f\",LE=%d$$\n",psm_durations[i],i);
DocPrint(doc,"\n$$MU,\"CANCEL\",LE=DOCM_CANCEL$$\n");
i=PopUpMenu(doc);
DocDel(doc);
return i;
}
U0 PsmRightClick(I64 x,I64 y)
{
U8 *st,*st2;
PsmNote *tmpn,*tmpn1;
I64 i,old_doc_flags;
if (DocPut) old_doc_flags=DocPut->flags;
psm.cur_note=tmpn=PsmFindNote(x,y);
if (tmpn!=&psm.head) {
Fs->win_inhibit=WIG_USER_TASK_DFT;
i=PopUpDuration;
if (0<=i<PSM_DURATIONS_NUM) {
if (tmpn->type==PSMT_NOTE)
tmpn->duration=i;
} else {
switch (i) {
case PSMR_REST:
if (tmpn->type==PSMT_NOTE)
tmpn->ona=ONA_REST;
break;
case PSMR_SHARP:
if (tmpn->type==PSMT_NOTE && tmpn->ona!=ONA_REST) {
if (Btr(&tmpn->flags,PSMf_FLAT))
tmpn->ona++;
if (Btc(&tmpn->flags,PSMf_SHARP))
tmpn->ona--;
else
tmpn->ona++;
}
break;
case PSMR_FLAT:
if (tmpn->type==PSMT_NOTE && tmpn->ona!=ONA_REST) {
if (Btr(&tmpn->flags,PSMf_SHARP))
tmpn->ona--;
if (Btc(&tmpn->flags,PSMf_FLAT))
tmpn->ona++;
else
tmpn->ona--;
}
break;
case PSMR_TIE:
if (tmpn->type==PSMT_NOTE)
Btc(&tmpn->flags,PSMf_TIE);
break;
case PSMR_SET_WORD:
if (tmpn->type==PSMT_NOTE) {
if (DocPut) DocPut->flags&=~DOCF_FORM;
if (PsmHasWords(tmpn->word))
st2=MStrPrint("\nWord(\"%Q\"):",tmpn->word);
else
st2=MStrPrint("\nWord(\"\"):");
DocBottom;
st=GetStr(st2);
Free(st2);
Free(tmpn->word);
if (*st) {
tmpn->word=MStrPrint("%q",st);
Free(st);
} else
tmpn->word=StrNew(" ");
if (DocPut) DocPut->flags=DocPut->flags&
~DOCF_FORM|old_doc_flags&DOCF_FORM;
}
break;
case PSMR_INS_NOTE:
tmpn1=PsmNoteCopy(tmpn);
QueIns(tmpn1,tmpn);
break;
case PSMR_DELETE_NOTE:
psm.cur_note=tmpn->next;
QueRem(tmpn);
PsmNoteDel(tmpn);
break;
}
}
PsmSetWidth(psm.cur_note);
Fs->win_inhibit=WIG_TASK_DFT-WIF_SELF_FOCUS
-WIF_SELF_BORDER-WIF_FOCUS_TASK_MENU-WIF_SELF_CTRLS;
}
}
U0 PsmLeftClickPickNoteBox(I64 duration)
{
I64 o,n,msg_code,arg1,arg2;
PsmNote *tmpn,*tmpn1;
do {
msg_code=GetMsg(&arg1,&arg2,1<<MSG_MS_L_UP|1<<MSG_MS_MOVE);
if (msg_code==MSG_MS_MOVE) {
DrawDC2;
DrawNote(psm.dc2,arg1,arg2,duration);
}
} while (msg_code!=MSG_MS_L_UP);
if (arg2<13*FONT_HEIGHT) {
if (arg1>psm.head.last->x)
tmpn1=psm.head.last;
else if (arg1<psm.head.next->x)
tmpn1=&psm.head;
else
tmpn1=PsmFindNote(arg1-PSM_NOTE_SPACING/2,arg2);
tmpn=CAlloc(sizeof(PsmNote));
tmpn->type=PSMT_NOTE;
arg2=arg2/4-15;
n=arg2%7;
o=4+arg2/-7;
if (n<0) {
n+=7;
o++;
}
n=psm_note_inverse_map[n];
if (n<3)
o--;
tmpn->ona=Note2Ona(n,o);
tmpn->duration=duration;
PsmSetWidth(tmpn);
QueIns(tmpn,tmpn1);
psm.cur_note=tmpn->next;
}
DrawDC2;
}
U0 PsmLeftClickPickMeterBox(I64 top,I64 bottom)
{
I64 msg_code,arg1,arg2;
PsmNote *tmpn,*tmpn1;
do {
msg_code=GetMsg(&arg1,&arg2,1<<MSG_MS_L_UP|1<<MSG_MS_MOVE);
if (msg_code==MSG_MS_MOVE) {
DrawDC2;
DrawTimeSignature(psm.dc2,arg1,arg2,top,bottom);
}
} while (msg_code!=MSG_MS_L_UP);
if (arg2<13*FONT_HEIGHT) {
if (arg1>=psm.head.x)
tmpn1=psm.head.last;
else if (arg1<psm.head.next->x)
tmpn1=&psm.head;
else
tmpn1=PsmFindNote(arg1-PSM_NOTE_SPACING/2,arg2);
tmpn=CAlloc(sizeof(PsmNote));
tmpn->type=PSMT_METER;
tmpn->meter_top=top;
tmpn->meter_bottom=bottom;
PsmSetWidth(tmpn);
QueIns(tmpn,tmpn1);
psm.cur_note=tmpn->next;
}
DrawDC2;
}
U0 PsmLeftClickStaffPtr(I64 x,I64 y)
{
PsmNote *tmpn,*tmpn1;
I64 o,n,msg_code,arg1,arg2,n_original,o_original;
psm.cur_note=tmpn=PsmFindNote(x,y);
if (tmpn!=&psm.head) {
if (tmpn->type==PSMT_NOTE) {
o_original=Ona2Octave(tmpn->ona);
n_original=Ona2Note (tmpn->ona);
do {
msg_code=GetMsg(&arg1,&arg2,1<<MSG_MS_L_UP|1<<MSG_MS_MOVE);
if (msg_code==MSG_MS_L_UP) {
tmpn1=PsmFindNote(arg1,arg2);
if (tmpn1==&psm.head || tmpn1==tmpn)
goto move_note;
else {
Free(tmpn1->word);
tmpn1->word=tmpn->word;
tmpn->word=NULL;
tmpn->ona=Note2Ona(n_original,o_original);
}
} else {
move_note:
arg2=arg2/4-15;
n=arg2%7;
o=4+arg2/-7;
if (n<0) {
n+=7;
o++;
}
n=psm_note_inverse_map[n];
if (n<3)
o--;
tmpn->ona=Note2Ona(n,o);
}
} while (msg_code!=MSG_MS_L_UP);
PsmSetWidth(tmpn);
}
}
}
U0 PsmLeftClickStaffBox(I64 x,I64 y)
{
I64 msg_code,arg1,arg2;
do {
msg_code=GetMsg(&arg1,&arg2,1<<MSG_MS_L_UP|1<<MSG_MS_MOVE);
DrawDC2;
psm.dc2->color=ROPF_DITHER+WHITE<<16+BLACK;
GrBorder(psm.dc2,x,y,arg1,arg2);
if (msg_code==MSG_MS_L_UP) {
if (x>arg1) SwapI64(&x,&arg1);
PsmMarkSel(x,arg1,TRUE);
}
} while (msg_code!=MSG_MS_L_UP);
DrawDC2;
}
U0 PsmLeftClick(I64 x,I64 y)
{
I64 duration,top,bottom;
if (y<13*FONT_HEIGHT) {
if (psm.tool==PSMTT_PTR_TOOL)
PsmLeftClickStaffPtr(x,y);
else
PsmLeftClickStaffBox(x,y);
} else {
duration=PsmGetPickNoteBoxDuration(x,y);
if (0<=duration<PSM_DURATIONS_NUM)
PsmLeftClickPickNoteBox(duration);
else if (PsmGetPickMeterBox(x,y,&top,&bottom))
PsmLeftClickPickMeterBox(top,bottom);
else if (PsmGetPickToolBox(x,y))
DrawDC2;
}
}
U8 PsmCvtDuration(F64 d)
{
F64 d1,d2;
I64 j;
for (j=0;j<PSM_DURATIONS_NUM;j++) {
d1=psm_durations[j];
d2=psm_durations[j+1];
if (d<d1*d2/(d1+d2))
return j;
}
return 0;
}
#define PSM_KEYS_NUM 20
class PsmKey
{
U8 x,w,h,ascii;
};
#define PSM_W_W 16
#define PSM_W_H 36
#define PSM_B_W 8
#define PSM_B_H 20
PsmKey psm_kbd[PSM_KEYS_NUM]={
{ 2*PSM_W_W-4,PSM_B_W,PSM_B_H,'e' },
{ 3*PSM_W_W-4,PSM_B_W,PSM_B_H,'r' },
{ 4*PSM_W_W-4,PSM_B_W,PSM_B_H,'t' },
{ 6*PSM_W_W-4,PSM_B_W,PSM_B_H,'u' },
{ 7*PSM_W_W-4,PSM_B_W,PSM_B_H,'i' },
{ 9*PSM_W_W-4,PSM_B_W,PSM_B_H,'p' },
{10*PSM_W_W-4,PSM_B_W,PSM_B_H,'[' },
{11*PSM_W_W-4,PSM_B_W,PSM_B_H,']' },
{ 0*PSM_W_W,PSM_W_W,PSM_W_H,'a' },
{ 1*PSM_W_W,PSM_W_W,PSM_W_H,'s' },
{ 2*PSM_W_W,PSM_W_W,PSM_W_H,'d' },
{ 3*PSM_W_W,PSM_W_W,PSM_W_H,'f' },
{ 4*PSM_W_W,PSM_W_W,PSM_W_H,'g' },
{ 5*PSM_W_W,PSM_W_W,PSM_W_H,'h' },
{ 6*PSM_W_W,PSM_W_W,PSM_W_H,'j' },
{ 7*PSM_W_W,PSM_W_W,PSM_W_H,'k' },
{ 8*PSM_W_W,PSM_W_W,PSM_W_H,'l' },
{ 9*PSM_W_W,PSM_W_W,PSM_W_H,';' },
{10*PSM_W_W,PSM_W_W,PSM_W_H,'\'' },
{11*PSM_W_W,PSM_W_W,PSM_W_H,'\n'},
};
U0 PsmDownKey(I64 x,I64 y)
{
I64 i;
PsmKey *o;
y-=FONT_HEIGHT*13;
if (0<=y<PSM_W_H) {
x-=16;
for (i=0;i<PSM_KEYS_NUM;i++) {
o=&psm_kbd[i];
if (o->x<=x<o->x+o->w && y<o->h) {
Msg(MSG_KEY_DOWN,o->ascii,0);
return;
}
}
}
}
U0 PsmUpKey(I64 x,I64 y)
{
I64 i;
PsmKey *o;
y-=FONT_HEIGHT*13;
if (0<=y<PSM_W_H) {
x-=16;
for (i=0;i<PSM_KEYS_NUM;i++) {
o=&psm_kbd[i];
if (o->x<=x<o->x+o->w && y<o->h) {
Msg(MSG_KEY_UP,o->ascii,0);
return;
}
}
}
}
U0 PsmPushMode(I64 psm_octave)
{
Fs->win_inhibit=WIG_TASK_DFT-WIF_SELF_FOCUS
-WIF_SELF_BORDER-WIF_FOCUS_TASK_MENU-WIF_SELF_CTRLS;
PsmMenu(psm_octave);
}
U0 PsmPopMode()
{
Fs->win_inhibit=WIG_USER_TASK_DFT;
DCFill;
}
#define PSMF_CD 1
#define PSMF_INCOMPLETE 2
U0 Psalmody(U8 *dirname="~/Psalmody")
{
Bool was_playing,is_null=TRUE,was_null=TRUE;
I64 arg1,arg2,msg_code=0,col,ona=ONA_REST,last_ona=ONA_REST,
psm_octave=4,timeout_val,timeout_val2,old_doc_flags;
U8 *filename=NULL,*st,*st2;
PsmNote *tmpn;
F64 psm_duration=1.0,d,evt_time=tS,note_down_time=tS;
CCtrl *c=TempoNew;
if (DocPut) old_doc_flags=DocPut->flags;
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
MusicSettingsRst;
tempo_state.tempo=Round(TEMPO_RANGE*(music.tempo-0.5)/4.4);
tempo_state.stacatto=Round(TEMPO_RANGE*(music.stacatto_factor-0.12)/0.88);
if (DocPut) DocPut->flags|=DOCF_FORM;
MemSet(&psm,0,sizeof(PsmCtrl));
psm.scrn_x=0;
psm.head.next=psm.head.last=&psm.head;
psm.clipboard.next=psm.clipboard.last=&psm.clipboard;
psm.cur_note=&psm.head;
psm.dc2=DCAlias;
MenuPush(
"File {"
" New(,'.');"
" ChgDir(MSG_CMD,PSMF_CD);"
" Open(,CH_CTRLO);"
" SaveAs(,CH_CTRLA);"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Edit {"
" Cut(,CH_CTRLX);"
" Copy(,CH_CTRLC);"
" Paste(,CH_CTRLV);"
" RightMenu(,'\n');"
" BackSpace(,CH_BACKSPACE);"
" DeleteNote(,,SC_DELETE);"
" ClearSong(,'.');"
" Left(,,SC_CURSOR_LEFT);"
" Right(,,SC_CURSOR_RIGHT);"
" GoBegin(,,0x4CB0000044B);"
" GoEnd(,,0x4CD0000044D);"
"}"
"Song {"
" Play(,'x');"
" Record(,'z');"
" Random(,',');"
" MarkIncomplete(MSG_CMD,PSMF_INCOMPLETE);"
"}"
"Snd {"
" Octave1(,'1');"
" Octave2(,'2');"
" Octave3(,'3');"
" Octave4(,'4');"
" Octave5(,'5');"
" Octave6(,'6');"
" Octave7(,'7');"
"}"
"Help {"
" Help(,,SC_F1);"
"}"
);
psm.incomplete_entry=MenuEntryFind(Fs->cur_menu,"Song/MarkIncomplete");
psm.record_entry=MenuEntryFind(Fs->cur_menu,"Song/Record");
AutoComplete;
WinBorder;
WinMax;
dirname=StrNew(dirname);
PsmPushMode(psm_octave);
col=0;
Fs->draw_it=&DrawIt;
try {
while (TRUE) {
was_playing=FALSE;
mo_start:
if (ms.pos_text.y-Fs->win_top<18)
msg_code=GetMsg(&arg1,&arg2,1<<MSG_KEY_DOWN|1<<MSG_KEY_UP|
1<<MSG_MS_L_DOWN|1<<MSG_MS_L_UP|1<<MSG_MS_R_UP|
1<<MSG_MS_MOVE|1<<MSG_CMD);
else
msg_code=GetMsg(&arg1,&arg2,1<<MSG_KEY_DOWN|1<<MSG_KEY_UP|
1<<MSG_MS_MOVE|1<<MSG_CMD);
mo_got_msg:
if (msg_code==MSG_KEY_DOWN && arg1==CH_SPACE && !arg2) {
//The Window Mgr sets the Doc cur_entry to a bttn
//and generates a <SPACE> when the Doc Bttns are clicked.
//This is so that kbd and mouse are the same for Doc's.
//We must now pass the <SPACE> onto the Doc hndlr.
PutKey(arg1,arg2);
goto mo_start;
}
if (msg_code!=MSG_MS_MOVE) {
DocBottom;
if (was_playing || DocPut->cur_entry->y>=Fs->win_height-2) {
PsmMenu(psm_octave);
col=0;
}
}
ona=Note2Ona(3,psm_octave+1); //C
is_null=TRUE;
switch (msg_code) {
case MSG_CMD:
PsmPopMode;
switch (arg1) {
case PSMF_CD:
st2=dirname;
if (dirname=PopUpPickDir) {
Free(st2);
Free(filename);
filename=NULL;
} else
dirname=st2;
break;
case PSMF_INCOMPLETE:
psm.incomplete_entry->checked=!psm.incomplete_entry->checked;
break;
}
PsmPushMode(psm_octave);
col=0;
break;
case MSG_KEY_DOWN:
evt_time=tS;
if ('0'<=arg1<='9') {
psm_octave=arg1-'0';
PsmMenu(psm_octave);
col=0;
} else {
switch (arg1) {
start:
case 'a': ona-=8; break;
case 's': ona-=7; break;
case 'e': ona-=6; break;
case 'd': ona-=5; break;
case 'r': ona-=4; break;
case 'f': ona-=3; break;
case 't': ona-=2; break;
case 'g': ona--; break;
case 'h': break;
case 'u': ona++; break;
case 'j': ona+=2; break;
case 'i': ona+=3; break;
case 'k': ona+=4; break;
case 'l': ona+=5; break;
case 'p': ona+=6; break;
case ';': ona+=7; break;
case '[': ona+=8; break;
case '\'': ona+=9; break;
case ']': ona+=10; break;
case CH_SPACE: ona=ONA_REST; break;
end:
is_null=FALSE;
break;
case 0:
switch (arg2.u8[0]) {
case SC_CURSOR_LEFT:
if (arg2&SCF_CTRL) {
while (psm.cur_note->last!=&psm.head) {
psm.cur_note=psm.cur_note->last;
if (psm.cur_note!=&psm.head)
LBEqu(&psm.cur_note->flags,PSMf_SEL,arg2&SCF_SHIFT);
}
} else {
if (psm.cur_note->last!=&psm.head) {
psm.cur_note=psm.cur_note->last;
if (psm.cur_note!=&psm.head)
LBEqu(&psm.cur_note->flags,PSMf_SEL,arg2&SCF_SHIFT);
}
}
break;
case SC_CURSOR_RIGHT:
if (arg2&SCF_CTRL) {
while (psm.cur_note!=&psm.head) {
if (psm.cur_note!=&psm.head)
LBEqu(&psm.cur_note->flags,PSMf_SEL,arg2&SCF_SHIFT);
psm.cur_note=psm.cur_note->next;
}
} else {
if (psm.cur_note!=&psm.head) {
if (psm.cur_note!=&psm.head)
LBEqu(&psm.cur_note->flags,PSMf_SEL,arg2&SCF_SHIFT);
psm.cur_note=psm.cur_note->next;
}
}
break;
case SC_DELETE:
if (arg2&SCF_SHIFT)
PsmCutToClipboard;
else {
tmpn=psm.cur_note;
psm.cur_note=tmpn->next;
if (tmpn!=&psm.head) {
QueRem(tmpn);
PsmNoteDel(tmpn);
}
}
break;
case SC_INS:
if (arg2&SCF_SHIFT)
PsmPasteClipboard;
else if (arg2&SCF_CTRL)
PsmCopyToClipboard;
break;
case SC_F1:
PsmPopMode;
PopUpEd("::/Apps/Psalmody/Help.DD.Z",Fs);
PsmPushMode(psm_octave);
col=0;
break;
}
break;
case ',':
Free(filename);
filename=NULL;
PsmPopMode;
music.octave=psm_octave;
if (st2=GodSongStr) {
PsmLoadSongStr(st2,&psm_octave,&psm_duration);
Free(st2);
}
PsmPushMode(psm_octave);
col=0;
break;
case CH_CTRLO:
PsmPopMode;
RegOneTimePopUp(ARf_PSALMODY_JUKEBOX,
"Sel a song and preview it.\n"
"$$GREEN$$<SHIFT-ESC>$$FG$$ to load it into Psalmody.\n\n"
ST_WARN_ST " Graphics and other embelishments\n"
"will be lost because Psalmody can't\n"
"parse HolyC programs completely.\n");
Free(filename);
filename=NULL;
JukeBox(dirname,&filename);
if (filename) {
psm.scrn_x=0;
psm_duration=1.0;
psm_octave=4;
PsmSongDel(&psm.head);
psm.cur_note=&psm.head;
PsmLoadSong(filename,&psm_octave,&psm_duration);
psm.record_entry->checked=FALSE;
psm.cur_note=psm.head.next;
}
PsmPushMode(psm_octave);
col=0;
break;
case CH_CTRLA:
PsmPopMode;
filename=PsmSaveSong(dirname,filename);
PsmPushMode(psm_octave);
break;
case CH_CTRLC:
PsmCopyToClipboard;
break;
case CH_CTRLV:
PsmPasteClipboard;
break;
case CH_CTRLX:
PsmCutToClipboard;
break;
case '.':
PsmMenu(psm_octave);
col=0;
Free(filename);
filename=NULL;
psm_duration=1.0;
psm_octave=4;
PsmSongDel(&psm.head);
psm.cur_note=&psm.head;
psm.scrn_x=0;
break;
case '\n':
if (psm.cur_note!=&psm.head)
PsmRightClick(psm.cur_note->x,psm.cur_note->y);
break;
case 'x':
if (was_playing)
break;
col=0;
psm.playing=TRUE;
PsmMenu(psm_octave);
tmpn=psm.cur_note;
while (tmpn!=&psm.head) {
if (tmpn->type!=PSMT_METER) {
timeout_val=cnts.jiffies;
if (ms.pos_text.y-Fs->win_top<18)
msg_code=ScanMsg(&arg1,&arg2,1<<MSG_KEY_DOWN|
1<<MSG_MS_L_DOWN|1<<MSG_MS_R_UP|1<<MSG_CMD);
else
msg_code=ScanMsg(&arg1,&arg2,1<<MSG_KEY_DOWN|
1<<MSG_MS_L_DOWN|1<<MSG_CMD);
if (msg_code) {
Snd;
psm.playing=FALSE;
was_playing=TRUE;
if (ms.pos_text.y-Fs->win_top>=18 &&
msg_code==MSG_MS_L_DOWN)
goto mo_start;
else
goto mo_got_msg;
}
psm.cur_note=tmpn;
psm.scrn_x+=tmpn->x-0.33*GR_WIDTH;
if (PsmHasWords(tmpn->word))
"%s",tmpn->word;
Snd(tmpn->ona);
music.tempo=4.4*tempo_state.tempo/TEMPO_RANGE+0.5;
music.stacatto_factor=
0.88*tempo_state.stacatto/TEMPO_RANGE+0.12;
d=JIFFY_FREQ*psm_durations[tmpn->duration]/music.tempo;
if (Bt(&tmpn->flags,PSMf_TIE)) {
timeout_val+=d;
timeout_val2=timeout_val;
} else {
timeout_val+=d*music.stacatto_factor;
timeout_val2=timeout_val+
d*(1.0-music.stacatto_factor);
}
SleepUntil(timeout_val);
Snd;
SleepUntil(timeout_val2);
}
tmpn=tmpn->next;
}
psm.cur_note=&psm.head;
psm.scrn_x+=psm.cur_note->x-GR_WIDTH/2;
psm.playing=FALSE;
PsmMenu(psm_octave);
col=0;
Snd;
break;
case CH_BACKSPACE:
tmpn=psm.cur_note->last;
if (tmpn!=&psm.head) {
QueRem(tmpn);
PsmNoteDel(tmpn);
}
if (col) {
'' CH_BACKSPACE;
col--;
}
break;
case 'z':
if (psm.record_entry->checked)
psm.record_entry->checked=FALSE;
else {
psm.record_entry->checked=TRUE;
psm_duration=1.0;
psm_octave=4;
psm.scrn_x=0;
}
PsmMenu(psm_octave);
col=0;
break;
case CH_ESC:
PsmPopMode;
filename=PsmSaveSong(dirname,filename);
PsmPushMode(psm_octave);
case CH_SHIFT_ESC:
goto mo_done;
}
}
break;
case MSG_KEY_UP:
evt_time=tS;
break;
case MSG_MS_MOVE:
if (arg2>18*FONT_HEIGHT)
Fs->win_inhibit=WIG_USER_TASK_DFT;
else
Fs->win_inhibit=WIG_TASK_DFT-WIF_SELF_FOCUS-WIF_SELF_BORDER
-WIF_FOCUS_TASK_MENU-WIF_SELF_CTRLS;
break;
case MSG_MS_L_DOWN:
PsmDownKey(arg1,arg2);
PsmLeftClick(arg1,arg2);
break;
case MSG_MS_L_UP:
PsmUpKey(arg1,arg2);
break;
default:
PsmRightClick(arg1,arg2);
}
if (is_null)
ona=ONA_REST;
if (ona!=last_ona || is_null!=was_null) {
if (ona==ONA_REST) {
if (is_null)
st="";
else
st="R";
} else
st=LstSub(Ona2Note(ona),psm_note_lst);
Snd(ona);
if (psm.record_entry->checked) {
if (!was_null) {
music.tempo=4.4*tempo_state.tempo/TEMPO_RANGE+0.5;
music.stacatto_factor=0.88*tempo_state.stacatto/TEMPO_RANGE+0.12;
tmpn->duration=PsmCvtDuration(
music.tempo*(evt_time-note_down_time));
PsmSetWidth(tmpn);
QueIns(tmpn,psm.cur_note->last);
}
if (!is_null) {
note_down_time=tS;
tmpn=CAlloc(sizeof(PsmNote));
tmpn->type=PSMT_NOTE;
tmpn->ona=ona;
if (st[1]=='#')
Bts(&tmpn->flags,PSMf_SHARP);
}
}
last_ona=ona;
was_null=is_null;
"%s",st;
col+=StrLen(st);
if (col>=Fs->win_width-1) {
'\n';
col=0;
}
}
}
mo_done:
GetMsg(,,1<<MSG_KEY_UP);
} catch
PutExcept;
PsmPopMode;
PsmSongDel(&psm.head);
PsmSongDel(&psm.clipboard);
TempoDel(c);
DCFill;
DCDel(psm.dc2);
DocClear;
SettingsPop;
if (DocPut) DocPut->flags=DocPut->flags&~DOCF_FORM|old_doc_flags&DOCF_FORM;
Free(dirname);
MenuPop;
}
+3
View File
@@ -0,0 +1,3 @@
Cd(__DIR__);;
#include "Load"
Psalmody;
+1
View File
@@ -0,0 +1 @@
MkDir("~/Span");
+10
View File
@@ -0,0 +1,10 @@
#help_index "Games"
Cd(__DIR__);;
#include "Span.HH"
#include "SpanDerive"
#include "SpanBridge"
#include "SpanNew"
#include "SpanMain"
#help_index ""
+3
View File
@@ -0,0 +1,3 @@
Cd(__DIR__);;
#include "Load"
Span;
+49
View File
@@ -0,0 +1,49 @@
#define SPAN_VERSION 1.0
class SpanHeader
{
F64 version;
I32 num_masses,num_springs;
};
class MyMass:CMass
{
F64 radius,cost,load_t;
CColorROPU32 color;
} *cursor_mass;
class MySpring:CSpring
{
F64 compression_strength,tensile_strength,cost;
F64 base_compression_strength,base_tensile_strength,
base_const,base_cost;
CColorROPU32 color;
I32 pen_width;
};
CMathODE *ode=NULL;
CCtrlBttnState run_bttn,mode_bttn;
CColorROPU32 run_colors[2]={RED,GREEN};
#define MD_MASS 0
#define MD_CONCRETE 1
#define MD_STEEL 2
#define MD_WIRE 3
#define MD_MOVE 4
#define MD_DELETE 5
#define MD_MODES_NUM 6
CColorROPU32 mode_colors[MD_MODES_NUM]=
{BROWN,LTGRAY,DKGRAY,RED,PURPLE,RED};
DefineLstLoad("ST_SPAN_MODES","Mass\0Concrete\0Steel\0Wire\0Move\0Delete\0");
class SpanAnimateStruct
{
U8 *saved_ode;
F64 elapsed_t,start_wall_t;
} a;
extern MyMass *PlaceMass(I64 x, I64 y);
extern F64 SpanTime();
+80
View File
@@ -0,0 +1,80 @@
#define STRENGTH_SCALE 1.5e7
#define SPRING_SCALE 6.0e6
#define COST_SCALE 375.0
#define MASS_RADIUS 3.0
#define MASS_MASS 10.0
#define WIRE_PERCENT 0.99
#define RIVER_BANK_COLS 5
#define SKY_LINES 40
#define FIXED_X1 ((RIVER_BANK_COLS-1)*FONT_WIDTH)
#define FIXED_X2 ((RIVER_BANK_COLS-4)*FONT_WIDTH)
#define FIXED_X3 (TEXT_COLS*FONT_WIDTH>>1)
#define FIXED_Y1 ((SKY_LINES+1)*FONT_HEIGHT)
#define FIXED_Y2 ((SKY_LINES+5)*FONT_HEIGHT)
#define FIXED_Y3 ((TEXT_ROWS-8)*FONT_HEIGHT)
#define LOAD_WEIGHTS 8
U0 SpanBridge1Init(CMathODE *)
{
I64 i;
MyMass *tmpm;
tmpm=PlaceMass(GR_WIDTH-FIXED_X1,FIXED_Y1);
tmpm->flags|=MSF_FIXED;
tmpm=PlaceMass(GR_WIDTH-FIXED_X2,FIXED_Y1);
tmpm->flags|=MSF_FIXED;
tmpm=PlaceMass(GR_WIDTH-FIXED_X1,FIXED_Y2);
tmpm->flags|=MSF_FIXED;
tmpm=PlaceMass(FIXED_X1,FIXED_Y1);
tmpm->flags|=MSF_FIXED;
tmpm=PlaceMass(FIXED_X2,FIXED_Y1);
tmpm->flags|=MSF_FIXED;
tmpm=PlaceMass(FIXED_X1,FIXED_Y2);
tmpm->flags|=MSF_FIXED;
tmpm=PlaceMass(FIXED_X3,FIXED_Y3);
tmpm->flags|=MSF_FIXED;
for (i=0;i<LOAD_WEIGHTS;i++) {
tmpm=PlaceMass(FIXED_X1+(i+1)*(GR_WIDTH-2*FIXED_X1)/(LOAD_WEIGHTS+1),
FIXED_Y1);
tmpm->load_t=(i+1.0)/LOAD_WEIGHTS;
tmpm->color=RED;
}
DocClear;
"$$BG,LTCYAN$$%h*c",SKY_LINES,'\n';
for (i=0;i<10;i++) {
"$$BG,BROWN$$%h*c",RIVER_BANK_COLS,CH_SPACE;
"$$BG,LTCYAN$$%h*c",TEXT_COLS-2*RIVER_BANK_COLS,CH_SPACE;
"$$BG,BROWN$$%h*c\n",RIVER_BANK_COLS,CH_SPACE;
}
for (i=0;i<5;i++) {
"$$BG,BROWN$$%h*c",RIVER_BANK_COLS+i,CH_SPACE;
"$$BG,BLUE$$%h*c",TEXT_COLS/2-RIVER_BANK_COLS-2*i,CH_SPACE;
"$$BG,BROWN$$%h*c",2*i,CH_SPACE;
"$$BG,BLUE$$%h*c",TEXT_COLS/2-RIVER_BANK_COLS-2*i,CH_SPACE;
"$$BG,BROWN$$%h*c\n",RIVER_BANK_COLS+i,CH_SPACE;
}
}
U0 AdjustLoads(CMathODE *ode)
{
MyMass *tmpm=ode->next_mass;
F64 d,tt=SpanTime/10.0;
while (tmpm!=&ode->next_mass) {
if (tmpm->load_t) {
if (tt) {
d=Abs(Sin(tmpm->load_t*ã+tt)); //0.0<=d<=1.0
tmpm->mass=100.0*Sqr(Sqr(d+1.0));
tmpm->radius=7.0*d+2.0;
} else {
tmpm->mass=MASS_MASS;
tmpm->radius=MASS_RADIUS;
}
}
tmpm=tmpm->next;
}
}
+47
View File
@@ -0,0 +1,47 @@
U0 MyDerivative(CMathODE *ode,F64,COrder2D3 *,COrder2D3 *)
{
//The forces due to springs and drag are
//automatically handled by the
//ode code. We can add new forces
//here.
CTask *task=ode->win_task;
F64 d,dd;
CD3 p,p2;
MyMass *tmpm1,*tmpm2;
//Collisions
tmpm1=ode->next_mass;
while (tmpm1!=&ode->next_mass) {
tmpm2=tmpm1->next;
while (tmpm2!=&ode->next_mass) {
D3Sub(&p,&tmpm2->state->x,&tmpm1->state->x);
dd=D3NormSqr(&p);
if (dd<=Sqr(tmpm1->radius+tmpm2->radius)) {
d=Sqrt(dd)+0.0001;
dd=10.0*Sqr(Sqr(Sqr(tmpm1->radius+tmpm2->radius)-dd));
D3MulEqu(&p,dd/d);
D3AddEqu(&tmpm2->DstateDt->DxDt,&p);
D3SubEqu(&tmpm1->DstateDt->DxDt,&p);
}
tmpm2=tmpm2->next;
}
tmpm1=tmpm1->next;
}
tmpm1=ode->next_mass;
while (tmpm1!=&ode->next_mass) {
if (!(tmpm1->flags&MSF_FIXED))
tmpm1->DstateDt->DyDt+=10.0*tmpm1->mass; //Gravity
tmpm1=tmpm1->next;
}
if (cursor_mass) {
p2.x=ms.pos.x-task->pix_left-task->scroll_x;
p2.y=ms.pos.y-task->pix_top-task->scroll_y;
p2.z=0;
D3Sub(&p,&p2,&cursor_mass->state->x);
d=10.0*D3NormSqr(&p);
D3MulEqu(&p,d);
D3AddEqu(&cursor_mass->DstateDt->DxDt,&p);
}
}
+468
View File
@@ -0,0 +1,468 @@
F64 SpanTime()
{
if (run_bttn.state)
return a.elapsed_t+tS-a.start_wall_t;
else
return a.elapsed_t;
}
F64 Cost(CMathODE *ode)
{
MyMass *tmpm;
MySpring *tmps;
F64 res=0;
tmpm=ode->next_mass;
while (tmpm!=&ode->next_mass) {
res+=tmpm->cost;
tmpm=tmpm->next;
}
tmps=ode->next_spring;
while (tmps!=&ode->next_spring) {
res+=tmps->cost;
tmps=tmps->next;
}
return res;
}
U0 DrawIt(CTask *task,CDC *dc)
{
MyMass *tmpm;
MySpring *tmps;
tmps=ode->next_spring;
while (tmps!=&ode->next_spring) {
if (!(tmps->flags&SSF_INACTIVE)) {
dc->color=tmps->color;
dc->pen_width=tmps->pen_width;
GrLine3(dc,tmps->end1->x,tmps->end1->y,0,
tmps->end2->x,tmps->end2->y,0);
}
tmps=tmps->next;
}
if (cursor_mass) {
dc->color=RED;
dc->pen_width=2;
GrLine3(dc,ms.pos.x-task->pix_left-task->scroll_x,
ms.pos.y-task->pix_top-task->scroll_y,0,
cursor_mass->x,cursor_mass->y,0);
}
tmpm=ode->next_mass;
while (tmpm!=&ode->next_mass) {
if (!(tmpm->flags&MSF_INACTIVE)) {
dc->color=BLACK;
GrCircle(dc,tmpm->x,tmpm->y,tmpm->radius);
GrFloodFill(dc,tmpm->x,tmpm->y,TRUE);
dc->color=tmpm->color;
GrCircle(dc,tmpm->x,tmpm->y,tmpm->radius);
GrFloodFill(dc,tmpm->x,tmpm->y,TRUE);
dc->color=BLACK;
GrCircle(dc,tmpm->x,tmpm->y,tmpm->radius);
}
tmpm=tmpm->next;
}
dc->color=BLACK;
GrPrint(dc,90,0,"Cost:%12.2,f",Cost(ode));
GrPrint(dc,90,FONT_HEIGHT,"Time:%12.2f",SpanTime);
}
MyMass *PlaceMass(I64 x, I64 y)
{
MyMass *tmpm=CAlloc(sizeof(MyMass));
tmpm->drag_profile_factor=1.0;
tmpm->x=x;
tmpm->y=y;
tmpm->mass=MASS_MASS;
tmpm->radius=MASS_RADIUS;
tmpm->cost=25.0*COST_SCALE;
tmpm->color=YELLOW;
QueIns(tmpm,ode->last_mass);
return tmpm;
}
U0 NullSpring(MySpring *tmps,F64 scale)
{
F64 d=D3Dist(&tmps->end1->x,&tmps->end2->x);
tmps->rest_len=d*scale;
tmps->compression_strength=
tmps->base_compression_strength/(tmps->rest_len+1.0);
tmps->tensile_strength=tmps->base_tensile_strength/(tmps->rest_len+1.0);
tmps->const=tmps->base_const/(tmps->rest_len+1.0);
tmps->cost=tmps->base_cost*tmps->rest_len;
}
U0 MoveMass(MyMass *tmpm,I64 x, I64 y)
{
MySpring *tmps;
tmpm->x=x;
tmpm->y=y;
tmpm->DxDt=0;
tmpm->DyDt=0;
tmps=ode->next_spring;
while (tmps!=&ode->next_spring) {
if (tmps->end1==tmpm || tmps->end2==tmpm) {
if (tmps->flags&SSF_NO_COMPRESSION)
NullSpring(tmps,WIRE_PERCENT);
else
NullSpring(tmps,1.0);
}
tmps=tmps->next;
}
}
U0 DelSpring(MySpring *tmps)
{
QueRem(tmps);
Free(tmps);
}
U0 DelMass(MyMass *tmpm)
{
MySpring *tmps,*tmps1;
tmps=ode->next_spring;
while (tmps!=&ode->next_spring) {
tmps1=tmps->next;
if (tmps->end1==tmpm || tmps->end2==tmpm)
DelSpring(tmps);
tmps=tmps1;
}
QueRem(tmpm);
Free(tmpm);
}
U0 DrawSpring(CDC *dc,MyMass *tmpm,I64 x,I64 y)
{
switch (mode_bttn.state) {
case MD_CONCRETE:
dc->color=LTGRAY;
dc->pen_width=2;
break;
case MD_STEEL:
dc->color=DKGRAY;
dc->pen_width=2;
break;
case MD_WIRE:
dc->color=RED;
dc->pen_width=1;
break;
}
GrLine3(dc,tmpm->x,tmpm->y,0,x,y,0);
}
U0 PlaceSpring(MyMass *tmpm1,MyMass *tmpm2)
{
MySpring *tmps=CAlloc(sizeof(MySpring));
tmps->end1=tmpm1;
tmps->end2=tmpm2;
switch (mode_bttn.state) {
case MD_CONCRETE:
tmps->base_const = 3.00*SPRING_SCALE;
tmps->base_compression_strength=10.00*STRENGTH_SCALE;
tmps->base_tensile_strength = 0.35*STRENGTH_SCALE;
tmps->base_cost = 0.30*COST_SCALE;
NullSpring(tmps,1.0);
tmps->color=LTGRAY;
tmps->pen_width=2;
break;
case MD_STEEL:
tmps->base_const = 1.00*SPRING_SCALE;
tmps->base_compression_strength= 1.00*STRENGTH_SCALE;
tmps->base_tensile_strength = 1.00*STRENGTH_SCALE;
tmps->base_cost = 1.00*COST_SCALE;
NullSpring(tmps,1.0);
tmps->color=DKGRAY;
tmps->pen_width=2;
break;
case MD_WIRE:
tmps->base_const = 0.25*SPRING_SCALE;
tmps->base_compression_strength= 0.00;
tmps->base_tensile_strength = 0.50*STRENGTH_SCALE;
tmps->base_cost = 0.10*COST_SCALE;
NullSpring(tmps,WIRE_PERCENT);
tmps->color=RED;
tmps->pen_width=1;
tmps->flags|=SSF_NO_COMPRESSION;
break;
}
QueIns(tmps,ode->last_spring);
}
U0 AnimateTask(SpanAnimateStruct *a)
{
MySpring *tmps,*tmps1;
Bool old_run=FALSE;
F64 f;
while (TRUE) {
tmps=ode->next_spring;
while (tmps!=&ode->next_spring) {
tmps1=tmps->next;
f=tmps->f;
if (f>0 && f>tmps->compression_strength &&
!(tmps->flags&SSF_NO_COMPRESSION)||
f<0 && -f>tmps->tensile_strength &&
!(tmps->flags&SSF_NO_TENSION))
tmps->flags|=SSF_INACTIVE;
tmps=tmps1;
}
AdjustLoads(ode);
Refresh; //CMathODE updated once per refresh.
if (old_run!=run_bttn.state) {
if (run_bttn.state) {
if (!a->elapsed_t || !a->saved_ode) {
Free(a->saved_ode);
a->saved_ode=SpanSave(ode);
}
a->start_wall_t=tS;
ode->flags&=~ODEF_PAUSED;
} else {
ode->flags|=ODEF_PAUSED;
a->elapsed_t+=tS-a->start_wall_t;
}
old_run=run_bttn.state;
}
}
}
U0 Init(SpanAnimateStruct *a)
{
SpanDel(ode);
ode=SpanNew;
run_bttn.state=0;
Refresh(2); //Allow stop to reg in animate task.
if (a->saved_ode)
SpanLoad(ode,a->saved_ode);
else
SpanBridge1Init(ode);
a->elapsed_t=0;
cursor_mass=NULL;
}
U0 SongTask(I64)
{//Song by Terry A. Davis
Fs->task_end_cb=&SndTaskEndCB;
MusicSettingsRst;
music.tempo= 3.636;
music.stacatto_factor= 0.902;
while (TRUE) {
Play("5q.EeDqED4G5DhE");
Play("5q.EeDqED4G5DhE");
Play("5q.FeEFEqF4G5EhF");
Play("5q.FeEFEqF4G5EhF");
}
}
U0 Span()
{
I64 msg_code,arg1,arg2;
MyMass *tmpm1=NULL,*tmpm2=NULL;
MySpring *tmps;
CCtrl *bt_run,*bt_mode;
U8 *src;
CDC *dc=DCAlias;
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
Fs->text_attr=BROWN<<4+BLACK;
AutoComplete;
WinBorder;
WinMax;
DocCursor;
Fs->song_task=Spawn(&SongTask,NULL,"Song",,Fs);
bt_run =CtrlBttnNew(0,0, 80,,
2,"Stopped\0Running\0",run_colors,&run_bttn);
bt_mode=CtrlBttnNew(0,3.0*FONT_HEIGHT,80,,
MD_MODES_NUM,Define("ST_SPAN_MODES"),mode_colors,&mode_bttn);
a.saved_ode=NULL;
Fs->win_inhibit|=WIG_DBL_CLICK;
MenuPush(
"File {"
" New(,CH_CTRLN);"
" Open(,CH_CTRLO);"
" SaveAs(,CH_CTRLA);"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" Restart(,'\n');"
" RunStop(,CH_SPACE);"
" Mass(,'m');"
" Concrete(,'c');"
" Steel(,'s');"
" Wire(,'w');"
" Move(,'v');"
" Delete(,'d');"
"}"
);
ode=NULL;
Init(&a);
Fs->animate_task=Spawn(&AnimateTask,&a,"Animate",,Fs);
Fs->draw_it=&DrawIt;
PopUpOk(
"Build a bridge to hold-up the\n"
"red masses. Test your design\n"
"by pressing run/stop.\n\n"
"The lowest cost bridge that\n"
"stays standing wins.\n\n"
"For a variation, try without\n"
"using the center base point.\n"
"\n"
"Use\n"
"\t$$GREEN$$'m'$$FG$$ass\n"
"\t$$GREEN$$'c'$$FG$$oncrete\n"
"\t$$GREEN$$'s'$$FG$$teel\n"
"\t$$GREEN$$'w'$$FG$$ire\n"
"\nto sel materials.\n");
try {
while (TRUE) {
msg_code=GetMsg(&arg1,&arg2,1<<MSG_MS_L_DOWN|1<<MSG_MS_R_DOWN|
1<<MSG_MS_L_UP|1<<MSG_KEY_DOWN|1<<MSG_MS_MOVE);
DCFill(dc);
switch (msg_code) {
case MSG_MS_L_DOWN:
cursor_mass=tmpm1=tmpm2=NULL;
switch (mode_bttn.state) {
case MD_MASS:
PlaceMass(arg1,arg2);
break;
case MD_CONCRETE:
case MD_STEEL:
case MD_WIRE:
tmpm1=MassFind(ode,arg1,arg2);
break;
case MD_MOVE:
if (run_bttn.state)
cursor_mass=MassFind(ode,arg1,arg2);
else
if (tmpm1=MassFind(ode,arg1,arg2))
MoveMass(tmpm1,arg1,arg2);
break;
case MD_DELETE:
MassOrSpringFind(ode,&tmpm1,&tmps,arg1,arg2);
if (tmpm1)
DelMass(tmpm1);
if (tmps)
DelSpring(tmps);
break;
}
break;
case MSG_MS_L_UP:
switch (mode_bttn.state) {
case MD_CONCRETE:
case MD_STEEL:
case MD_WIRE:
if (tmpm1 && (tmpm2=MassFind(ode,arg1,arg2)) && tmpm1!=tmpm2)
PlaceSpring(tmpm1,tmpm2);
break;
case MD_MOVE:
if (!run_bttn.state && tmpm1)
MoveMass(tmpm1,arg1,arg2);
break;
}
cursor_mass=tmpm1=tmpm2=NULL;
break;
case MSG_MS_MOVE:
switch (mode_bttn.state) {
case MD_MOVE:
if (!run_bttn.state && tmpm1)
MoveMass(tmpm1,arg1,arg2);
break;
case MD_CONCRETE:
case MD_STEEL:
case MD_WIRE:
if (tmpm1) {
DrawSpring(dc,tmpm1,arg1,arg2);
}
break;
}
break;
case MSG_MS_R_DOWN:
mode_bttn.state++;
if (mode_bttn.state>=MD_MODES_NUM)
mode_bttn.state=0;
cursor_mass=tmpm1=tmpm2=NULL;
break;
case MSG_KEY_DOWN:
switch (arg1) {
case '\n':
if (!SpanTime || !a.saved_ode) {
Free(a.saved_ode);
a.saved_ode=SpanSave(ode);
}
Init(&a);
break;
case CH_CTRLN:
Free(a.saved_ode);
a.saved_ode=NULL;
Init(&a);
break;
case CH_CTRLO:
if (src=SpanRead) {
Free(a.saved_ode);
a.saved_ode=src;
Init(&a);
}
break;
case CH_CTRLA:
if (!SpanTime || !a.saved_ode) {
Free(a.saved_ode);
a.saved_ode=SpanSave(ode);
}
Init(&a);
SpanWrite(ode);
break;
case CH_SPACE:
run_bttn.state=!run_bttn.state;
break;
case 'c':
mode_bttn.state=MD_CONCRETE;
break;
case 's':
mode_bttn.state=MD_STEEL;
break;
case 'w':
mode_bttn.state=MD_WIRE;
break;
case 'm':
mode_bttn.state=MD_MASS;
break;
case 'v':
mode_bttn.state=MD_MOVE;
break;
case 'd':
mode_bttn.state=MD_DELETE;
break;
case CH_ESC:
if (!SpanTime || !a.saved_ode) {
Free(a.saved_ode);
a.saved_ode=SpanSave(ode);
}
Init(&a);
SpanWrite(ode);
case CH_SHIFT_ESC:
goto span_done;
}
break;
}
}
span_done: //Don't goto out of try
GetMsg(,,1<<MSG_KEY_UP);
} catch
PutExcept;
DocClear;
SettingsPop;
CtrlBttnDel(bt_run);
CtrlBttnDel(bt_mode);
SpanDel(ode);
DCFill(dc);
DCDel(dc);
MenuPop;
}
+126
View File
@@ -0,0 +1,126 @@
CMathODE *SpanNew()
{
CMathODE *ode=ODENew(0,1e-4,ODEF_HAS_MASSES|ODEF_PAUSED);
ode->derivative=&MyDerivative;
ode->drag_v2=0.002;
ode->drag_v3=0.00001;
ode->acceleration_limit=5e3;
QueIns(ode,Fs->last_ode);
return ode;
}
U0 SpanDel(CMathODE *ode)
{
if (ode) {
QueRem(ode);
QueDel(&ode->next_mass,TRUE);
QueDel(&ode->next_spring,TRUE);
ODEDel(ode);
}
}
#define M_SIZE (sizeof(MyMass) -offset(CMass.start))
#define S_SIZE (sizeof(MySpring)-offset(CSpring.start))
U8 *SpanSave(CMathODE *ode,I64 *_size=NULL)
{
I64 cnt;
U8 *res,*ptr;
MyMass *tmpm;
MySpring *tmps;
SpanHeader h;
ODERenum(ode);
h.version=SPAN_VERSION;
if (ode->next_mass!=&ode->next_mass)
h.num_masses=ode->last_mass->num+1;
else
h.num_masses=0;
if (ode->next_spring!=&ode->next_spring)
h.num_springs=ode->last_spring->num+1;
else
h.num_springs=0;
cnt=sizeof(SpanHeader)+h.num_masses*M_SIZE+h.num_springs*S_SIZE;
ptr=res=MAlloc(cnt);
MemCpy(ptr,&h,sizeof(SpanHeader));
ptr+=sizeof(SpanHeader);
tmpm=ode->next_mass;
while (tmpm!=&ode->next_mass) {
MemCpy(ptr,&tmpm->start,M_SIZE);
ptr+=M_SIZE;
tmpm=tmpm->next;
}
tmps=ode->next_spring;
while (tmps!=&ode->next_spring) {
MemCpy(ptr,&tmps->start,S_SIZE);
ptr+=S_SIZE;
tmps=tmps->next;
}
if (_size) *_size=cnt;
return res;
}
Bool SpanWrite(CMathODE *ode)
{
U8 *name,*buf;
I64 size;
Bool res=FALSE,old_silent=Silent;
MkDir("~/Span");
Silent(old_silent);
if (name=PopUpFileName("~/Span/Game.DATA")) {
if (buf=SpanSave(ode,&size)) {
FileWrite(name,buf,size);
Free(buf);
res=TRUE;
}
Free(name);
}
return res;
}
U0 SpanLoad(CMathODE *ode,U8 *src)
{
I64 i;
MyMass *tmpm;
MySpring *tmps;
SpanHeader h;
if (!src) return;
MemCpy(&h,src,sizeof(SpanHeader));
src+=sizeof(SpanHeader);
for (i=0;i<h.num_masses;i++) {
tmpm=CAlloc(sizeof(MyMass));
MemCpy(&tmpm->start,src,M_SIZE);
src+=M_SIZE;
QueIns(tmpm,ode->last_mass);
}
for (i=0;i<h.num_springs;i++) {
tmps=CAlloc(sizeof(MySpring));
MemCpy(&tmps->start,src,S_SIZE);
src+=S_SIZE;
QueIns(tmps,ode->last_spring);
tmps->end1=MassFindNum(ode,tmps->end1_num);
tmps->end2=MassFindNum(ode,tmps->end2_num);
}
}
U8 *SpanRead()
{
U8 *src=NULL,*name;
Bool old_silent=Silent;
MkDir("~/Span");
Silent(old_silent);
if (name=PopUpPickFile("~/Span")) {
src=FileRead(name);
Free(name);
}
return src;
}
+6
View File
@@ -0,0 +1,6 @@
#help_index "Games"
Cd(__DIR__);;
#include "Strut"
#help_index ""
+3
View File
@@ -0,0 +1,3 @@
Cd(__DIR__);;
#include "Load"
Strut;
+635
View File
@@ -0,0 +1,635 @@
$BG,0$
$SP,"<1>",BI=1$
$SP,"<2>",BI=2$
$SP,"<3>",BI=3$
$BG$
#define STARS_NUM 8192
I64 stars_x[STARS_NUM],stars_y[STARS_NUM];
#define RADIUS 7
class MyMass:CMass
{
U8 *img;
};
class MySpring:CSpring
{
I64 type,action_key;
};
//Main Modses
#define MMD_EDIT 0
#define MMD_PLAY 1
#define MMD_MODES_NUM 2
CColorROPU32 main_mode_colors[MMD_MODES_NUM]={LTRED,LTGREEN};
DefineLstLoad("ST_MAIN_MODES","Edit\0Play\0");
CCtrlBttnState main_mode_bttn;
//Edit Modes
#define EMD_MASS 0
#define EMD_SPRING 1
#define EMD_CONNECTOR 2
#define EMD_THRUSTER 3
#define EMD_MOVE 4
#define EMD_MODES_NUM 5
CColorROPU32 edit_mode_colors[EMD_MODES_NUM]={LTGRAY,LTCYAN,CYAN,YELLOW,LTBLUE};
DefineLstLoad("ST_EDIT_MODES","Mass\0Spring\0Connector\0Thruster\0Move\0");
CCtrlBttnState edit_mode_bttn;
CTask *task;
F64 zoom;
I64 next_action_key,action_scan_codes[10];
CMathODE *ode=NULL;
U0 S2W(F64 sx,F64 sy,F64 *_wx,F64 *_wy)
{
sx-=task->pix_left+task->scroll_x;
sy-=task->pix_top +task->scroll_y;
*_wx=sx/zoom;
*_wy=sy/zoom;
}
U0 W2S(F64 wx,F64 wy,F64 *_sx,F64 *_sy)
{
*_sx=wx*zoom; *_sy=wy*zoom;
}
#define ZOOM_STEPS 20
U0 Zoom(F64 d)
{
F64 sx,sy,wx,wy;
I64 i,x=ms.pos.x,y=ms.pos.y;
d=Exp(Ln(d)/ZOOM_STEPS);
for (i=0;i<ZOOM_STEPS;i++) {
S2W(x,y,&wx,&wy);
zoom=Clamp(zoom*d,0.02,50);
W2S(wx,wy,&sx,&sy);
task->scroll_x=ms.pos.x-sx-task->pix_left;
task->scroll_y=ms.pos.y-sy-task->pix_top;
Sleep(10);
}
}
U0 DrawIt(CTask *,CDC *dc)
{
I64 i;
F64 é,d,x1,y1,x2,y2;
MyMass *tmpm;
MySpring *tmps;
tmpm=ode->next_mass;
if (tmpm!=&ode->next_mass) {
task->scroll_x=-tmpm->x*zoom+task->pix_width >>1;
task->scroll_y=-tmpm->y*zoom+task->pix_height>>1;
}
dc->flags|=DCF_TRANSFORMATION;
Mat4x4Scale(dc->r,zoom);
switch (main_mode_bttn.state) {
case MMD_EDIT:
task->text_attr=DKGRAY<<4+WHITE;
dc->color=BLACK;
break;
case MMD_PLAY:
task->text_attr=BLACK<<4+WHITE;
dc->color=WHITE;
for (i=0;i<STARS_NUM;i++)
GrPlot3(dc,stars_x[i],stars_y[i],0);
break;
}
if (main_mode_bttn.state==MMD_EDIT) {
if (edit_mode_bttn.state==EMD_CONNECTOR) {
dc->color=CYAN;
S2W(FONT_WIDTH*11,FONT_HEIGHT*7,&x1,&y1);
GrPutChar3(dc,x1,y1,0,next_action_key);
} else if (edit_mode_bttn.state==EMD_THRUSTER) {
dc->color=YELLOW;
S2W(FONT_WIDTH*11,FONT_HEIGHT*7,&x1,&y1);
GrPutChar3(dc,x1,y1,0,next_action_key);
}
}
tmps=ode->next_spring;
while (tmps!=&ode->next_spring) {
if (tmps->type==EMD_SPRING) {
dc->color=LTCYAN;
GrLine3(dc,tmps->end1->x,tmps->end1->y,0,
tmps->end2->x,tmps->end2->y,0);
} else if (tmps->type==EMD_CONNECTOR) {
dc->color=CYAN;
GrLine3(dc,tmps->end1->x,tmps->end1->y,0,
tmps->end2->x,tmps->end2->y,0);
}
tmps=tmps->next;
}
dc->color=LTGRAY;
tmpm=ode->next_mass;
while (tmpm!=&ode->next_mass) {
Sprite3(dc,tmpm->x,tmpm->y,0,tmpm->img);
tmpm=tmpm->next;
}
tmps=ode->next_spring;
while (tmps!=&ode->next_spring) {
x1=tmps->end1->x; y1=tmps->end1->y;
x2=tmps->end2->x; y2=tmps->end2->y;
if (tmps->type==EMD_THRUSTER) {
é=Arg(x2-x1,y2-y1);
if (Bt(kbd.down_bitmap,action_scan_codes[tmps->action_key-'0'])) {
dc->flags|=DCF_SYMMETRY;
DCSymmetry3Set(dc,x1,y1,256,x1,y1,0,x1-256*Cos(é),y1-256*Sin(é),0);
for (i=0;i<8;i++) {
d=20*Rand+6;
if (d<10)
dc->color=BLUE;
else if (d<16)
dc->color=LTBLUE;
else
dc->color=YELLOW;
GrLine3(dc,x1-3*Cos(é),y1-3*Sin(é),0,
x1-d*Cos(é)+0.5*d*Sin(é),
y1-d*Sin(é)-0.5*d*Cos(é),0);
GrLine3(dc,x1-2*d*Cos(é),y1-2*d*Sin(é),0,
x1-d*Cos(é)+0.5*d*Sin(é),
y1-d*Sin(é)-0.5*d*Cos(é),0);
}
dc->flags&=~DCF_SYMMETRY;
}
Sprite3ZB(dc,x1,y1,0,$IB,"<3>",BI=3$,é);
if (zoom>0.5) {
dc->color=YELLOW;
GrPutChar3(dc,(x1*7+x2)/8,(y1*7+y2)/8,0,tmps->action_key);
}
} else if (tmps->type==EMD_CONNECTOR) {
if (zoom>0.5) {
dc->color=CYAN;
GrPutChar3(dc,(x1*7+x2)/8,(y1*7+y2)/8,0,tmps->action_key);
}
}
tmps=tmps->next;
}
}
U0 MyDerivative(CMathODE *ode,F64,COrder2D3 *,COrder2D3 *)
{
//The forces due to springs and drag are
//automatically handled by the
//ode code. We can add new forces
//here.
F64 d,dd;
CD3 p;
MyMass *tmpm1,*tmpm2;
MySpring *tmps;
tmpm1=ode->next_mass;
while (tmpm1!=&ode->next_mass) {
tmpm2=tmpm1->next;
while (tmpm2!=&ode->next_mass) {
D3Sub(&p,&tmpm2->state->x,&tmpm1->state->x);
dd=D3NormSqr(&p);
if (dd<=Sqr(2*RADIUS)) {
d=Sqrt(dd)+0.0001;
dd=10.0*Sqr(Sqr(Sqr(2*RADIUS)-dd));
D3MulEqu(&p,dd/d);
D3AddEqu(&tmpm2->DstateDt->DxDt,&p);
D3SubEqu(&tmpm1->DstateDt->DxDt,&p);
}
tmpm2=tmpm2->next;
}
tmpm1=tmpm1->next;
}
tmps=ode->next_spring;
while (tmps!=&ode->next_spring) {
if (main_mode_bttn.state==MMD_PLAY && tmps->type==EMD_THRUSTER &&
Bt(kbd.down_bitmap,action_scan_codes[tmps->action_key-'0'])) {
D3Sub(&p,&tmps->end2->state->x,&tmps->end1->state->x);
D3Unit(&p);
D3MulEqu(&p,2000);
D3AddEqu(&tmps->end1->DstateDt->DxDt,&p);
}
tmps=tmps->next;
}
}
MyMass *PlaceMass(I64 x, I64 y)
{
MyMass *tmpm=CAlloc(sizeof(MyMass));
tmpm->mass=1.0;
tmpm->drag_profile_factor=100.0;
tmpm->x=x;
tmpm->y=y;
QueIns(tmpm,ode->last_mass);
return tmpm;
}
MySpring *PlaceSpring(MyMass *tmpm1,MyMass *tmpm2,I64 type)
{
MySpring *tmps=CAlloc(sizeof(MySpring));
F64 d=D3Dist(&tmpm1->x,&tmpm2->x);
tmps->end1=tmpm1;
tmps->end2=tmpm2;
tmps->rest_len=d;
tmps->type=type;
if (type==EMD_THRUSTER)
tmps->const=0;
else
tmps->const=2500000/Sqr(d);
tmps->action_key=next_action_key;
QueIns(tmps,ode->last_spring);
return tmps;
}
U0 CenterMasses()
{
CD3 p;
MyMass *tmpm1,*tmpm2;
tmpm1=ode->next_mass;
if (tmpm1!=&ode->next_mass) {
D3Copy(&p,&tmpm1->x);
tmpm2=ode->next_mass;
while (tmpm2!=&ode->next_mass) {
D3SubEqu(&tmpm2->x,&p);
tmpm2=tmpm2->next;
}
}
}
U0 NullSprings()
{
MySpring *tmps=ode->next_spring;
while (tmps!=&ode->next_spring) {
tmps->rest_len=D3Dist(&tmps->end1->x,&tmps->end2->x);
tmps=tmps->next;
}
}
U0 BreakConnectors()
{
MySpring *tmps=ode->next_spring,*tmps1;
while (tmps!=&ode->next_spring) {
tmps1=tmps->next;
if (tmps->type==EMD_CONNECTOR &&
Bt(kbd.down_bitmap,action_scan_codes[tmps->action_key-'0'])) {
QueRem(tmps);
Free(tmps);
}
tmps=tmps1;
}
}
U0 Init()
{
I64 i;
task=Fs;
for (i=0;i<=9;i++)
action_scan_codes[i]=Char2ScanCode('0'+i);
for (i=0;i<STARS_NUM;i++) {
stars_x[i]=RandU32%8192-4096;
stars_y[i]=RandU32%8192-4096;
}
next_action_key='1';
zoom=1.0;
ode=ODENew(0,1e-4,ODEF_HAS_MASSES);
ode->derivative=&MyDerivative;
ode->acceleration_limit=5e3;
ode->drag_v2=0.000002;
ode->drag_v3=0.0000001;
QueIns(ode,Fs->last_ode);
}
U0 CleanUp()
{
if (ode) {
QueRem(ode);
QueDel(&ode->next_mass,TRUE);
QueDel(&ode->next_spring,TRUE);
ODEDel(ode);
ode=NULL;
}
}
U0 PlayShip()
{
I64 arg1,arg2;
F64 last_noise=0;
Bool okay;
ode->flags&=~ODEF_PAUSED;
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Edit {"
" EditShip(,CH_SPACE);"
"}"
"Play {"
" Center(,'c');"
" Damp(,'d');"
" Action0(,'0');"
" Action1(,'1');"
" Action2(,'2');"
" Action3(,'3');"
" Action4(,'4');"
" Action5(,'5');"
" Action6(,'6');"
" Action7(,'7');"
" Action8(,'8');"
" Action9(,'9');"
"}"
"View {"
" ZoomIn(,'z');"
" ZoomOut(,'Z');"
"}"
);
DocClear;
try {
while (main_mode_bttn.state==MMD_PLAY) {
BreakConnectors;
switch (ScanMsg(&arg1,&arg2,1<<MSG_KEY_DOWN|1<<MSG_KEY_UP)) {
case MSG_KEY_DOWN:
switch (arg1) {
case '0'...'9':
if (tS>last_noise+0.25) {
Noise(250,18,46);
last_noise=tS;
}
break;
case 'z':
Spawn(&Zoom,2.0(I64));
break;
case 'Z':
Spawn(&Zoom,0.5(I64));
break;
case 'c':
CenterMasses;
break;
case 'd':
ode->drag_v2=0.002;
ode->drag_v3=0.0001;
break;
case CH_SPACE:
if (++main_mode_bttn.state==MMD_MODES_NUM)
main_mode_bttn.state=0;
GetMsg(,,1<<MSG_KEY_UP);
goto ps_done;
case CH_SHIFT_ESC:
case CH_ESC:
throw;
}
break;
case MSG_KEY_UP:
switch (arg1) {
case 'd':
ode->drag_v2=0.000002;
ode->drag_v3=0.0000001;
break;
}
break;
}
Refresh;
}
ps_done: //Don't goto out of try
okay=TRUE;
} catch {
Fs->catch_except=TRUE;
okay=FALSE;
}
MenuPop;
if (!okay)
throw;
}
U0 EditShip()
{
I64 arg1,arg2;
F64 wx,wy;
Bool okay;
MyMass *tmpm1=NULL,*tmpm2=NULL;
CCtrl *bt_edit_mode=CtrlBttnNew(0,5*FONT_HEIGHT+4,80,,EMD_MODES_NUM,
Define("ST_EDIT_MODES"),edit_mode_colors,&edit_mode_bttn);
ode->flags|=ODEF_PAUSED;
MenuPush(
"File {"
" Abort(,CH_SHIFT_ESC);"
" Exit(,CH_ESC);"
"}"
"Play {"
" PlayShip(,CH_SPACE);"
" Center(,'c');"
" Damp(,'d');"
"}"
"Edit {"
" Move(,'v');"
" Mass(,'m');"
" Spring(,'s');"
" Connector(,'n');"
" Thruster(,'t');"
" Restart(,'\n');"
" Action0(,'0');"
" Action1(,'1');"
" Action2(,'2');"
" Action3(,'3');"
" Action4(,'4');"
" Action5(,'5');"
" Action6(,'6');"
" Action7(,'7');"
" Action8(,'8');"
" Action9(,'9');"
"}"
"View {"
" ZoomIn(,'z');"
" ZoomOut(,'Z');"
"}"
);
DocClear;
try {
while (main_mode_bttn.state==MMD_EDIT) {
switch (ScanMsg(&arg1,&arg2,
1<<MSG_MS_L_DOWN|1<<MSG_MS_L_UP|1<<MSG_MS_R_DOWN|
1<<MSG_MS_MOVE|1<<MSG_KEY_DOWN|1<<MSG_KEY_UP)) {
case MSG_MS_L_DOWN:
switch (edit_mode_bttn.state) {
case EMD_MASS:
S2W(ms.pos.x,ms.pos.y,&wx,&wy);
tmpm1=PlaceMass(wx,wy);
if (ode->next_mass==tmpm1)
tmpm1->img=$IB,"<1>",BI=1$;
else
tmpm1->img=$IB,"<2>",BI=2$;
tmpm1=NULL;
break;
case EMD_SPRING:
case EMD_CONNECTOR:
case EMD_THRUSTER:
case EMD_MOVE:
S2W(ms.pos.x,ms.pos.y,&wx,&wy);
tmpm1=MassFind(ode,wx,wy);
tmpm2=NULL;
break;
}
break;
case MSG_MS_L_UP:
switch (edit_mode_bttn.state) {
case EMD_MASS:
break;
case EMD_SPRING:
case EMD_CONNECTOR:
case EMD_THRUSTER:
S2W(ms.pos.x,ms.pos.y,&wx,&wy);
if (tmpm1 && (tmpm2=MassFind(ode,wx,wy)) && tmpm1!=tmpm2)
PlaceSpring(tmpm1,tmpm2,edit_mode_bttn.state);
tmpm1=tmpm2=NULL;
break;
case EMD_MOVE:
S2W(ms.pos.x,ms.pos.y,&wx,&wy);
if (tmpm1) {
tmpm1->x=wx;
tmpm1->y=wy;
tmpm1->z=0;
NullSprings;
}
tmpm1=tmpm2=NULL;
break;
}
break;
case MSG_MS_MOVE:
switch (edit_mode_bttn.state) {
case EMD_MOVE:
S2W(ms.pos.x,ms.pos.y,&wx,&wy);
if (tmpm1) {
tmpm1->x=wx;
tmpm1->y=wy;
tmpm1->z=0;
NullSprings;
}
break;
}
break;
case MSG_MS_R_DOWN:
if (++edit_mode_bttn.state==EMD_MODES_NUM)
edit_mode_bttn.state=0;
break;
case MSG_MS_R_UP:
break;
case MSG_KEY_DOWN:
switch (arg1) {
case '\n':
CleanUp;
Init;
break;
case '0'...'9':
next_action_key=arg1;
break;
case 'c':
CenterMasses;
break;
case 'd':
ode->flags&=~ODEF_PAUSED;
ode->drag_v2=0.002;
ode->drag_v3=0.0001;
break;
case 'v':
edit_mode_bttn.state=EMD_MOVE;
break;
case 'm':
edit_mode_bttn.state=EMD_MASS;
break;
case 'n':
edit_mode_bttn.state=EMD_CONNECTOR;
break;
case 's':
edit_mode_bttn.state=EMD_SPRING;
break;
case 't':
edit_mode_bttn.state=EMD_THRUSTER;
break;
case 'z':
Spawn(&Zoom,2.0(I64));
break;
case 'Z':
Spawn(&Zoom,0.5(I64));
break;
case CH_SPACE:
if (++main_mode_bttn.state==MMD_MODES_NUM)
main_mode_bttn.state=0;
GetMsg(,,1<<MSG_KEY_UP);
goto es_done;
case CH_SHIFT_ESC:
case CH_ESC:
throw;
}
break;
case MSG_KEY_UP:
switch (arg1) {
case 'd':
ode->flags|=ODEF_PAUSED;
ode->drag_v2=0.000002;
ode->drag_v3=0.0000001;
break;
}
break;
}
Refresh;
}
es_done: //Don't goto out of try
okay=TRUE;
} catch {
Fs->catch_except=TRUE;
okay=FALSE;
}
MenuPop;
CtrlBttnDel(bt_edit_mode);
if (!okay)
throw;
}
U0 Strut()
{
CCtrl *bt_main_mode;
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
Fs->win_inhibit|=WIF_SELF_MS_L|WIF_SELF_MS_R|WIG_DBL_CLICK;
AutoComplete;
WinBorder;
WinMax;
DocCursor;
DocClear;
"\n$$WW,1$$$$PURPLE$$$$TX+CX,\"Build a ship.\"$$$$FG$$\n\n"
"Sel mass mode.\tLeft-click to place masses.\n"
"Sel spring mode.\tLeft-drag to make members.\n"
"Sel thruster mode.\tPress a digit, 0-9. Drag to make thruster.\n"
"Sel connector mode.\tPress a digit, 0-9. "
"Drag to make breakable connector.\n\n"
"Press $$GREEN$$<SPACE>$$FG$$ to run the game. Press digits to operate "
"thrusters and break connectors.\n\n"
"Press $$GREEN$$<z>$$FG$$ or $$GREEN$$<SHIFT-Z>$$FG$$ to zoom in/out.\n\n";
PressAKey;
bt_main_mode=CtrlBttnNew(
(GR_WIDTH-4*FONT_WIDTH-16)>>1,1*FONT_HEIGHT+4,80,,MMD_MODES_NUM,
Define("ST_MAIN_MODES"),main_mode_colors,&main_mode_bttn);
DocClear;
Init;
Fs->draw_it=&DrawIt;
try {
while (TRUE) {
EditShip;
PlayShip;
}
} catch {
CleanUp;
Fs->catch_except=TRUE;
}
SettingsPop;
CtrlBttnDel(bt_main_mode);
}
øÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÿÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ùÿÿÿöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+8
View File
@@ -0,0 +1,8 @@
if (!FileFind("~/TimeClock",,FUF_JUST_DIRS)) {
MkDir("~/TimeClock");
DocClear;
"After Loading, type $$GREEN$$PunchIn;$$FG$$, "
"$$GREEN$$PunchOut;$$FG$$ or $$GREEN$$TimeRep;$$FG$$\n"
"You might want to make PLUGINS for hot keys.\n\n\n";
}
+7
View File
@@ -0,0 +1,7 @@
#help_index "Misc"
Cd(__DIR__);;
#include "TimeClk"
#include "Install" //Might as well always install
#help_index ""
+151
View File
@@ -0,0 +1,151 @@
#define TIME_FILENAME "~/TimeClock/TimeFile.DATA.Z"
#define TET_EOF 0
#define TET_PUNCH_IN 1
#define TET_PUNCH_OUT 2
class TimeEntry
{
TimeEntry *next,*last;
U8 type;
CDate datetime;
U8 *desc;
};
U0 TimeFileRead(TimeEntry *header)
{
U8 *buf,*ptr;
I64 type;
TimeEntry *tmpt;
buf=FileRead(TIME_FILENAME);
if (!buf)
buf=CAlloc(1);
QueInit(header);
ptr=buf;
while (type=*ptr++) {
tmpt=CAlloc(sizeof(TimeEntry));
tmpt->type=type;
tmpt->datetime=*ptr(CDate *)++;
tmpt->desc=StrNew(ptr);
ptr+=StrLen(ptr)+1;
QueIns(tmpt,header->last);
}
Free(buf);
}
U0 TimeFileWrite(TimeEntry *header)
{
U8 *buf,*ptr;
TimeEntry *tmpt;
I64 size=1; //for EOF
tmpt=header->next;
while (tmpt!=header) {
size+=sizeof(U8)+sizeof(CDate)+StrLen(tmpt->desc)+1;
tmpt=tmpt->next;
}
buf=MAlloc(size);
ptr=buf;
tmpt=header->next;
while (tmpt!=header) {
*ptr++=tmpt->type;
*ptr(CDate *)++=tmpt->datetime;
StrCpy(ptr,tmpt->desc);
ptr+=StrLen(tmpt->desc)+1;
tmpt=tmpt->next;
}
*ptr=TET_EOF;
FileWrite(TIME_FILENAME,buf,size);
Free(buf);
}
U0 TimeEntriesDel(TimeEntry *header)
{
TimeEntry *tmpt=header->next,*tmpt1;
while (tmpt!=header) {
tmpt1=tmpt->next;
Free(tmpt->desc);
Free(tmpt);
tmpt=tmpt1;
}
Free(header);
}
public Bool TimeRep(TimeEntry **_header=NULL)
{
Bool is_in=FALSE,first=TRUE;
I64 week,cur_week=-1,week_total;
TimeEntry *tmpt,*header=MAlloc(sizeof(TimeEntry));
if (_header) *_header=header;
TimeFileRead(header);
tmpt=header->next;
while (tmpt!=header) {
week=tmpt->datetime.date/7; //TODO
if (week!=cur_week) {
if (!first) {
if (is_in)
week_total+=Now;
"Week Total:%T\n",week_total-local_time_offset;
} else
first=FALSE;
cur_week=week;
week_total=0;
}
if (tmpt->type==TET_PUNCH_IN) {
"$$RED$$IN ";
if (!is_in)
week_total-=tmpt->datetime;
is_in=TRUE;
} else {
"$$RED$$OUT";
if (is_in)
week_total+=tmpt->datetime;
is_in=FALSE;
}
" %D %T:$$FG$$\n%s\n",tmpt->datetime,tmpt->datetime,tmpt->desc;
tmpt=tmpt->next;
}
if (is_in)
week_total+=Now;
"$$RED$$Week Total:%T$$FG$$\n",week_total-local_time_offset;
if (!_header)
TimeEntriesDel(header);
return is_in;
}
public U0 PunchOut()
{
TimeEntry *tmpt,*header;
if (!TimeRep(&header))
"$$BK,1$$Already Punched-Out$$BK,0$$\n";
else {
tmpt=MAlloc(sizeof(TimeEntry));
tmpt->type=TET_PUNCH_OUT;
tmpt->datetime=Now;
"\nEnter Description.\nPress <ESC> when done.\n";
if (!(tmpt->desc=GetStr(,,GSF_WITH_NEW_LINE)))
tmpt->desc=CAlloc(1);
QueIns(tmpt,header->last);
TimeFileWrite(header);
}
TimeEntriesDel(header);
}
public U0 PunchIn()
{
TimeEntry *tmpt,*header;
if (TimeRep(&header))
"$$BK,1$$Already Punched-In$$BK,0$$\n";
else {
tmpt=MAlloc(sizeof(TimeEntry));
tmpt->type=TET_PUNCH_IN;
tmpt->datetime=Now;
"\nEnter Description.\nPress <ESC> when done.\n";
if (!(tmpt->desc=GetStr(,,GSF_WITH_NEW_LINE)))
tmpt->desc=CAlloc(1);
QueIns(tmpt,header->last);
TimeFileWrite(header);
}
TimeEntriesDel(header);
}
+6
View File
@@ -0,0 +1,6 @@
#help_index "Games"
Cd(__DIR__);;
#include "Titanium"
#help_index ""
+3
View File
@@ -0,0 +1,3 @@
Cd(__DIR__);;
#include "Load"
Titanium;
File diff suppressed because it is too large. Load diff
+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;
}
+6
View File
@@ -0,0 +1,6 @@
#help_index "Games"
Cd(__DIR__);;
#include "VocabQuiz"
#help_index ""
+3
View File
@@ -0,0 +1,3 @@
Cd(__DIR__);;
#include "Load"
VocabQuiz;
+57
View File
@@ -0,0 +1,57 @@
U8 *RandVocabWord()
{
I64 i;
U8 *ptr;
if (!acd.num_words)
return NULL;
i=RandU32%acd.num_words;
ptr=acd.word_lst;
while (i-- && *ptr==ACD_WORD_CHAR)
ptr+=StrLen(ptr)+3;
if (*ptr++!=ACD_WORD_CHAR)
return NULL;
else
return ptr;
}
U0 VocabQuiz()
{
I64 ch,i,num;
U8 *right_word,*words[4];
if (!FileFind(ACD_DEF_FILENAME)) {
"Uncompressed dictionary not present.\n";
return;
}
do {
right_word=RandVocabWord;
for (i=0;i<4;i++)
words[i]=RandVocabWord;
num=RandU32&3;
words[num]=right_word;
"$$WW,1$$$$CM-LE,5$$$$RED$$$$BK,1$$%s$$BK,0$$:$$FG$$$$LM,4$$\n",right_word;
for (i=0;i<4;i++)
"\n\n$$GREEN$$$$BT-X,\"%d\",LM=\"%d\"$$$$FG$$"
"$$LM,7$$%s\n$$LM,4$$",i+1,i+1,ACDDefGet(words[i]);
"\n\n$$LTBLUE$$Answer:$$FG$$";
do {
ch=GetKey(,TRUE);
DocBottom;
if ('1'<=ch<='4') {
'\n';
if (ch-'1'==num) {
"$$LTGREEN$$Correct\n$$FG$$";
Snd(74);
} else {
"$$LTRED$$Incorrect\n$$FG$$";
Snd(46);
}
Sleep(500);
Snd;
ACDPopUpDef(right_word);
break;
}
} while (ch!=CH_SHIFT_ESC && ch!=CH_ESC);
"$$LM,0$$\n";
} while (ch!=CH_SHIFT_ESC && ch!=CH_ESC);
}
+7
View File
@@ -0,0 +1,7 @@
#help_index "Games"
Cd(__DIR__);;
#include "XCCtrls"
#include "X-Caliber"
#help_index ""
+3
View File
@@ -0,0 +1,3 @@
Cd(__DIR__);;
#include "Load"
XCaliber;
File diff suppressed because it is too large. Load diff
+154
View File
@@ -0,0 +1,154 @@
#define LASER_TEMP_MAX 30.0
#define LASER_THRESHOLD_TEMP 10.0
#define MASS_TEMP_MAX 5.0
class CtrlPanelState
{
I64 shot_radius,fuse_time;
F64 laser_temperature;
Bool spacewalk;
} ctrl_panel;
#define CTRL_PANEL_SPACING 33
#define CTRL_PANEL_RANGE 30
#define CTRL_PANEL_BORDER 2
#define CTRL_PANEL_BTTN_SIZE 12
#define TMP_Y (+2)
U0 DrawCtrlPanelCtrl(CDC *dc,CCtrl *c)
{
CtrlPanelState *s=c->state;
F64 d,d_range;
dc->color=LTRED;
GrRect(dc, c->left,c->top,CTRL_PANEL_SPACING*3+2,
CTRL_PANEL_SPACING*2+CTRL_PANEL_RANGE+CTRL_PANEL_BTTN_SIZE);
dc->color=DKGRAY;
GrRect(dc, c->left+CTRL_PANEL_BORDER,c->top+CTRL_PANEL_BORDER,
CTRL_PANEL_SPACING*3+2-2*CTRL_PANEL_BORDER,
CTRL_PANEL_SPACING*2+CTRL_PANEL_RANGE+CTRL_PANEL_BTTN_SIZE
-2*CTRL_PANEL_BORDER);
dc->color=BLACK;
GrLine(dc,c->left+CTRL_PANEL_SPACING,(c->top+CTRL_PANEL_BTTN_SIZE)+
CTRL_PANEL_SPACING,c->left+CTRL_PANEL_SPACING,
(c->top+CTRL_PANEL_BTTN_SIZE)+CTRL_PANEL_SPACING+CTRL_PANEL_RANGE-1);
GrLine(dc,c->left+2*CTRL_PANEL_SPACING+1,(c->top+CTRL_PANEL_BTTN_SIZE)+
CTRL_PANEL_SPACING,c->left+2*CTRL_PANEL_SPACING+1,
(c->top+CTRL_PANEL_BTTN_SIZE)+CTRL_PANEL_SPACING+CTRL_PANEL_RANGE-1);
dc->color=BLACK;
GrRect(dc,(c->left+c->right+1)/2-9*FONT_WIDTH/2-3,
c->top+CTRL_PANEL_BORDER+(CTRL_PANEL_SPACING-FONT_HEIGHT)/2,
9*FONT_WIDTH+6,FONT_HEIGHT+6);
if (s->spacewalk)
dc->color=YELLOW;
else
dc->color=DKGRAY;
GrRect(dc,(c->left+c->right+1)/2-9*FONT_WIDTH/2-2,
c->top+CTRL_PANEL_BORDER+1+(CTRL_PANEL_SPACING-FONT_HEIGHT)/2,
9*FONT_WIDTH+4,FONT_HEIGHT+4);
dc->color=RED;
GrPrint(dc,(c->left+c->right+1)/2-9*FONT_WIDTH/2,
c->top+CTRL_PANEL_BORDER+3+
(CTRL_PANEL_SPACING-FONT_HEIGHT)/2,"SpaceWalk");
GrPrint(dc,c->left+CTRL_PANEL_SPACING-4*FONT_WIDTH/2,
(c->top+CTRL_PANEL_BTTN_SIZE)+
CTRL_PANEL_SPACING-FONT_HEIGHT-2,"Size");
GrPrint(dc,c->left+2*CTRL_PANEL_SPACING+1-4*FONT_WIDTH/2,
(c->top+CTRL_PANEL_BTTN_SIZE)+
CTRL_PANEL_SPACING-FONT_HEIGHT-2,"Fuse");
dc->color=LTRED;
GrPrint(dc,c->left+CTRL_PANEL_SPACING-FONT_WIDTH/2,
(c->top+CTRL_PANEL_BTTN_SIZE)+CTRL_PANEL_SPACING+CTRL_PANEL_RANGE+3,
"%d",s->shot_radius*10/CTRL_PANEL_RANGE);
GrPrint(dc,c->left+2*CTRL_PANEL_SPACING+1-FONT_WIDTH/2,
(c->top+CTRL_PANEL_BTTN_SIZE)+CTRL_PANEL_SPACING+CTRL_PANEL_RANGE+3,
"%d",s->fuse_time*10/CTRL_PANEL_RANGE);
GrRect(dc,c->left+CTRL_PANEL_SPACING-3,
(c->top+CTRL_PANEL_BTTN_SIZE)+CTRL_PANEL_SPACING+
CTRL_PANEL_RANGE-1-s->shot_radius-2 ,7,5);
GrRect(dc,c->left+2*CTRL_PANEL_SPACING+1-3,
(c->top+CTRL_PANEL_BTTN_SIZE)+CTRL_PANEL_SPACING+
CTRL_PANEL_RANGE-1-s->fuse_time-2,7,5);
dc->color=YELLOW;
GrRect(dc,c->left+CTRL_PANEL_SPACING-2,
(c->top+CTRL_PANEL_BTTN_SIZE)+CTRL_PANEL_SPACING+
CTRL_PANEL_RANGE-1-s->shot_radius-1 ,5,3);
GrRect(dc,c->left+2*CTRL_PANEL_SPACING+1-2,
(c->top+CTRL_PANEL_BTTN_SIZE)+CTRL_PANEL_SPACING+
CTRL_PANEL_RANGE-1-s->fuse_time-1,5,3);
d_range=c->right-c->left-5-5;
d=s->laser_temperature*d_range/LASER_TEMP_MAX;
dc->color=BLACK;
GrRect(dc,c->left+5-1,c->bottom+TMP_Y-2,d_range+2,2+1+1);
if (d>1.0) {
dc->color=GREEN;
GrRect(dc,c->left+5,c->bottom+TMP_Y-1,Min(d,d_range/3),2);
if (d>=d_range/3) {
dc->color=YELLOW;
GrRect(dc,c->left+5+d_range/3,c->bottom+TMP_Y-1,
Min(d,2*d_range/3)-d_range/3,2);
if (d>=2*d_range/3) {
dc->color=RED;
GrRect(dc,c->left+5+2*d_range/3,c->bottom+TMP_Y-1,d-2*d_range/3,2);
}
}
}
}
U0 UpdateDerivedCtrlPanelCtrl(CCtrl *c)
{
CtrlPanelState *s=c->state;
c->left=c->win_task->pix_width-(CTRL_PANEL_SPACING*3+2);
c->right=c->left+CTRL_PANEL_SPACING*3+2;
c->top=c->win_task->pix_height-(CTRL_PANEL_SPACING*2+
CTRL_PANEL_RANGE+CTRL_PANEL_BTTN_SIZE);
c->bottom=c->top+CTRL_PANEL_SPACING*2+CTRL_PANEL_RANGE;
s->shot_radius=ClampI64(s->shot_radius,0,CTRL_PANEL_RANGE-1);
s->fuse_time=ClampI64(s->fuse_time,0,CTRL_PANEL_RANGE-1);
}
U0 LeftClickCtrlPanel(CCtrl *c,I64 x,I64 y,Bool)
{
CtrlPanelState *s=c->state;
if (y<c->top+CTRL_PANEL_BORDER+(CTRL_PANEL_SPACING-FONT_HEIGHT)/2+
FONT_HEIGHT+6)
s->spacewalk=TRUE;
else {
if (x<(c->right+c->left)/2)
s->shot_radius=CTRL_PANEL_RANGE-1
-(y-(c->top+CTRL_PANEL_SPACING+CTRL_PANEL_BTTN_SIZE));
else
s->fuse_time=CTRL_PANEL_RANGE-1
-(y-(c->top+CTRL_PANEL_SPACING+CTRL_PANEL_BTTN_SIZE));
}
if (c->update_derived_vals)
(*c->update_derived_vals)(c);
}
CCtrl *CtrlPanelNew()
{
CCtrl *c=CAlloc(sizeof(CCtrl));
MemSet(&ctrl_panel,0,sizeof(ctrl_panel));
c->win_task=Fs;
c->flags=CTRLF_SHOW|CTRLF_CAPTURE_LEFT_MS;
c->type=CTRLT_GENERIC;
c->state=&ctrl_panel;
c->draw_it=&DrawCtrlPanelCtrl;
c->left_click=&LeftClickCtrlPanel;
c->update_derived_vals=&UpdateDerivedCtrlPanelCtrl;
QueIns(c,Fs->last_ctrl);
TaskDerivedValsUpdate;
return c;
}
U0 CtrlPanelDel(CCtrl *c)
{
QueRem(c);
Free(c);
}