A number of little improvements and the possibility for initial army placement.
To use that mode, change the variable "classic" in the first line of the code into 1 (in the final version, this will be nicely sollicited in an opening screen).
Each of your 7 countries will have one army, you can assign the remaining 13 armies yourself, by means of the already present "draft" method.
The data file is not given here, as it has not changed.
There is still a todo list. One of the activities is a (stand alone) tool to convert a piece of plain ASCCI text into a scrollable helpfile.
Code: Select all
' The game of Risk, version october 24, 2018
'
             classic=0   ' change to 1 for classic initial army placement
init_risk()
do
  init_round()
  for cp.nr=1 to 6
    init_player()
    if cp.play(1)=0 then continue
    if cp.nr=human then human_play(human) else ai_play()
    exit_player()
    next cp.nr
  exit_round()
  until stop
end
def init_round()
if .sflag then k=4 else k=3
for i=1 to .ns
  .state(i,3)+=.state(i,1)
  button i text floor(.state(i,k))
  next i
end def
def init_player()
p=cp.nr ! cp.ncp=state_count()
cp.draft=1+cont_count()
field "play" back color .col(p,1),.col(p,2),.col(p,3)
button "cards" show ! bc(p)
do
  if .cards(p)>4 then
    cp.draft+=10 ! .cards(p)=max(0,.cards(p)-3) ! bc(p)
    end if
  until .cards(p)<5
end def
def human_play(p)
'
'*****      draft phase
'
if cp.draft then 
drafty(p)
/*
  button "cont" show ! group2(1)
  button "strength" show ! field "draft" show
  button "troops" text "0" ! button "maxtr" text cp.draft
  lnr=0 ! ntr=0
  do slowdown
    if bp("strength") then disp_strength()
    if bp("less") and lnr>0 then
      if ntr=0 then ntr=cp.draft else ntr-=1
      button "troops" text ntr
      end if
    if bp("more") and lnr>0 then
      if ntr=cp.draft then ntr=0 else ntr+=1
      button "troops" text ntr
      end if
    if bp("okee") and lnr>0 then
      .state(lnr,3)+=ntr ! cp.draft-=ntr ! ntr=0
      button lnr text floor(.state(lnr,3))
      button "troops" text "0" ! button "maxtr" text cp.draft
      end if
    for i=1 to .ns
      if bp(str$(i)) and .state(i,2)=p then
        if i=lnr then lnr=0 else lnr=i
        end if
      next i
     until bp("cont")
  group2(0) ! field "draft" hide
*/
  end if
'
'*****      attack phase
'
field "attack" show ! group3(1)
lna=0 ! lnd=0 ! sp_flag=0 ! s_flag=0 ! c_flag=0
state_count()
do slowdown
  if lna>0 then ! button "att" text floor(.state(lna,3))
    else ! button "att" text ""
    end if
  if lnd>0 then ! button "def" text floor(.state(lnd,3))
    else ! button "def" text ""
    end if
  if bp("strength") then disp_strength()
  k=0
  for i=1 to .ns     ' check state buttons
    if bp(str$(i)) then ! k=i ! break! end if
    next i
  if k then          ' check self or foreign
    e=0
    for i=2 to cp.play(1)+1
      if k=cp.play(i) then ! e=1 ! break ! end if
      next i
    if lna=0 and lnd=0 and e=1 then 
      lna=k ! sign_fight(lna,1) ! goto done
      end if
    if lna>0 then
      nb=0           ' check neighbour state or not
      for j=1 to 6
        if .link(lna,j)=k then nb=1
        next j
      if k=lnd then
        sign_fight(lnd,-2) ! lnd=0 ! goto done
        end if
      if k=lna then
        if lnd>0 then ! sign_fight(lnd,-2) ! lnd=0 ! end if
        lna=0 ! sign_fight(k,-1) ! goto done
        end if
      if e=1 and k<>lna then
        sign_fight(lna,-1) ! lna=k ! sign_fight(lna,1)
        if lnd>0 then ! sign_fight(lnd,-2) ! lnd=0 ! end if
        goto done
        end if
      if nb=1 and e=0 then
        if lnd>0 then sign_fight(lnd,-2)
        lnd=k ! sign_fight(lnd,2)
        end if
      end if
    end if
done:
  if lnd=0 then nxt else quit=0
  do                    ' start attack cycles on this combi
    if bp("stop") then
      if s_flag=0 then
        s_flag=1 ! quit=0 ! button "stop" text "Stop"
        else
        quit=1 ! button "stop" text "Start" ! continue
        end if
      end if
    if s_flag=0 then ! slowdown ! continue ! end if
    if bp("speed") then
      sp_flag=1-sp_flag
      if sp_flag then ! button ("speed") text "Fast"
        else ! button ("speed") text "Slow"
        end if
      end if
    if sp_flag=0 then pause 1 else pause .3
    if bp("pause") then
      button ("pause") text "Go on"
      do ! slowdown ! until bp("pause")
      button ("pause") text "Pause"
      end if
    r=attack(.state(lna,3), .state(lnd,3),.state(lnd,4))
    if r=1 then
      .state(lnd,3)-=1 ! button "def" text floor(.state(lnd,3))
      button "ddef" text "-1" ! button "datt" text ""
      button lnd text floor(.state(lnd,3))
      else
      .state(lna,3)-=1 ! button "att" text floor(.state(lna,3))
      button "datt" text "-1" ! button "ddef" text ""
      button lna text max(1,floor(.state(lna,3)))
      end if
    if floor(.state(lnd,3))=0 then           ' victory 
      da=max(1,floor(.state(lna,3)/3)) ! beep
      .state(lnd,3)=da ! .state(lna,3)-=da
      defen=.state(lnd,2) ! .state(lnd,2)=p
      draw_state(lnd,p) ! .state(lnd,4)=0 ! state_count()
      dc=check_dead(defen)
      if dc then ! .cards(p)+=dc ! bc(p) ! end if
      c_flag=1 ! quit=1
      end if
    if floor(.state(lna,3))=1 then quit=1     ' end of fight
    until quit
  button "att" text "" ! button "datt" text ""
  button "def" text "" ! button "ddef" text ""
  button lna text max(1,floor(.state(lna,3)))
  button lnd text max(1,floor(.state(lnd,3)))
  button "stop" text "Start" ! button "speed" text "Slow"
  lna=0 ! lnd=0 ! s_flag=0 ! sp_flag=0
nxt:
  until bp("cont")
if c_flag=1 then
  .cards(p)+=1 ! bc(p) ! c_flag=0
  end if
'
'*****.       Move phase
'
group3(0) ! group2(1) ! maxmove=0
for i=1 to .ns
  if .state(i,2)=p then maxmove+=.state(i,1)
  next i
maxmove=int(2*maxmove)  ! button "maxtr" text maxmove
field "attack" hide ! field "move" show
lna=0 ! lnb=0 ! ntr=0 ! button "troops" text "0"
do slowdown
  if bp("strength") then disp_strength()
  k=0
  for i=1 to .ns     ' check state buttons
    if bp(str$(i)) then ! k=i ! break! end if
    next i
  if k=0 then m_label1
  e=0
  for i=2 to cp.play(1)+1
    if k=cp.play(i) then ! e=1 ! break ! end if
    next i
  if e=0 then continue
  if k=lna then
    sign_fight(lna,-1) ! lna=0
    if lnb>0 then ! sign_fight(lnb,-2) ! lnb=0 ! end if
    continue
    end if
  if k=lnb then ! sign_fight(lnb,-2) ! lnb=0 ! continue ! end if
  if lna=0 then ! lna=k ! sign_fight(lna,1) ! continue ! end if
  if lnb=0 then
    nb=0           ' check neighbour state or not
    for j=1 to 6 ! if .link(lna,j)=k then nb=1 ! next j
    if nb=0 then continue
    lnb=k ! sign_fight(lnb,2)
    end if
m_label1:
  if lna=0 or lnb=0 then nxt1
  lnr=floor(.state(lna,3)) ! if lnr<2 then continue
  if bp("less") then
    if ntr=0 then ntr=min(lnr-1,maxmove) else ntr-=1
    button "troops" text ntr
    end if
  if bp("more") then
    if ntr=maxmove then ntr=0 else ntr=min(lnr-1,ntr+1)
    button "troops" text ntr
    end if
  if bp("okee") then
    .state(lna,3)-=ntr ! button lna text floor(.state(lna,3))
    .state(lnb,3)+=ntr ! button lnb text floor(.state(lnb,3))
     maxmove-=ntr ! ntr=0 ! lna=0 ! lnb=0
    button "troops" text "0" ! button "maxtr" text maxmove
    end if
nxt1:
  until bp("cont")
field "move" hide
end def
def drafty(p)
  button "cont" show ! group2(1)
  button "strength" show ! field "draft" show
  button "troops" text "0" ! button "maxtr" text cp.draft
  lnr=0 ! ntr=0
  do slowdown
    if bp("strength") then disp_strength()
    if bp("less") and lnr>0 then
      if ntr=0 then ntr=cp.draft else ntr-=1
      button "troops" text ntr
      end if
    if bp("more") and lnr>0 then
      if ntr=cp.draft then ntr=0 else ntr+=1
      button "troops" text ntr
      end if
    if bp("okee") and lnr>0 then
      .state(lnr,3)+=ntr ! cp.draft-=ntr ! ntr=0
      button lnr text floor(.state(lnr,3))
      button "troops" text "0" ! button "maxtr" text cp.draft
      end if
    for i=1 to .ns
      if bp(str$(i)) and .state(i,2)=p then
        if i=lnr then lnr=0 else lnr=i
        end if
      next i
     until bp("cont")
  group2(0) ! field "draft" hide
end def
def exit_player()
end def
def exit_round()
for i=1 to .ns ! .state(i,4)=.9*.state(i,4)+1 ! next i
if bp("strength") then disp_strength()
end def
def attack(na,nd,f)
f=2-cos(0.3142*f) ! nd*=f                    
q=na/(na+nd) ! q=min(.8,q) ! q=max(.2,q)
if rnd(1)<q then return 1 else return -1
end def
def check_dead(r)
dead=1
for i=1 to .ns
  if .state(i,2)=r then ! dead=0 ! break ! end if
  next i
if dead then return .cards(r) else return 0
end def
def f_fld(ff$,c$)
if c$="g" then ! field ff$ back color 0,1,0
  else  ! field ff$ back color 1,0,0
  end if
field ff$ font name "MarkerFelt-Thin"
field ff$ font size 30
end def
def sign_state(s,c)
'for i=1 to 5
  draw_state(s,7) ! pause .1
  draw_state(s,c) ! pause .1
 ' next i
button s text max(1,int(.state(s,3)))
end def
def sign_fight(i,ind)
if ind>0 then
  if ind=1 then t$=chr$(9732) else t$=chr$(57629)
  button i text t$
  else ! button i text floor(.state(i,3))
  end if
end def
def bc(p)   '  update cards button
button "cards" text .cards(p)
pause .5
end def
def bp(a$) = button_pressed(a$)
def cp() ! end def
' {risk_lib}
def ai_play()
'
'*****    draft phase
p=cp.nr ! field "draft" show
nc=.cards(p) ! ns=cp.play(1)
button "cards" show ! button "cards" text nc ! pause .3
if nc>=3 then
  cp.draft+=2*nc+floor(nc/5)-1
  .cards(p)-=3
  end if
if cp.draft >=1 then
  for i=1 to cp.draft
    k=(i-1)%ns+2 ! st=cp.play(k) ! .state(st,3)+=1
    button st text int(.state(st,3))
    next i
  cp.draft=0
  end if
pause .5 ! field "draft" hide
'
'******     attack phase
dim tab_in(99,3),tab(99,3)
max_attacks=.ai(p,1) ! field "attack" show
start_odds=.ai(p,2) ! stop_odds=.ai(p,3)
won_flag=0 ! ntab=0
for i=2 to ns+1
  lnr=cp.play(i) ! n_att=.state(lnr,3)
  for j=1 to 6
    buur=.link(lnr,j)
    if buur=0 or .state(buur,2)=p then continue
    n_def=.state(buur,3)
    ntab+=1 ! tab_in(ntab,1)=lnr ! tab_in(ntab,2)=buur
    tab_in(ntab,3)=n_att/max(n_def,1)
    next j
  next i
tablesort(ntab,3,tab_in,tab,3)
for i=1 to min(max_attacks,ntab)
                                if touch_x(0)>-1 then stop
  nla=tab(i,1) ! nld=tab(i,2)
  d=.state(nld,2) ! if d=p then continue
  do
    n_att=.state(nla,3) ! n_def=.state(nld,3)
    odds=n_att/max(n_def,1)
    if odds<start_odds or n_att<=stop_odds then break
    v=attack(n_att,n_def,.state(nld,4))
    if v=1 then ! won_flag=1 ! .state(nld,3)-=1
      else ! .state(nla,3)-=1
      end if
      sign_state(nla,p) ! sign_state(nld,d)
    if .state(nld,3)<1 then
      .state(nld,2)=p ! .state(nld,4)=0
      dl=max(1,floor(.state(nla,3)/3))
      .state(nla,3)-=dl ! .state(nld,3)=dl
      sign_state(nla,p) ! sign_state(nld,p)
      .cards(p)+=check_dead(d)
      break
      end if
    until forever
  next i
  if won_flag then 
    .cards(p)+=1 ! button "cards" text .cards(p) ! pause .3
    end if
field "attack" hide
'
'*****      move phase
ns=state_count() ! field "move" show
for i=2 to ns+1
  dim buren(6)
  buur_flag=0 ! bsum=0 ! k=0
  lnr=cp.play(i) ! n_c=.state(lnr,3)
  for j=1 to 6
    b=.link(lnr,j)
    if b=0 then break
    if .state(b,2)<>p then ! buur_flag=1
      else ! k+=1 ! buren(k)=b ! bsum+=.state(b,3)
      end if
    next j
  if k=0 then continue
  nb=k ! mu=(n_c+bsum)/(nb+1)
  if buur_flag=0 then ! pot=n_c-1
    else
    if n_c>mu then pot=n_c-mu else pot=0
    end if
  if pot>0 then ! .state(lnr,3)-=pot ! dp=pot/nb ! end if
    for j=1 to nb ! .state(buren(j),3)+=dp ! next j
  next i
for i=1 to .ns ! button i text floor(.state(i,3)) ! next i
pause .5 ! field "move" hide
end def
def assign()
dim t(42)
for i=1 to 42 ! t(i)=i ! .state(i,3)=1 ! next i
for i=1 to 7 ! for s=1 to 6
  do ! r=1+rnd(42) ! k=t(r) ! until k
  .state(k,2)=s ! t(r)=0 ! draw_state(k,s)
  next s ! next i
for cp.nr=1 to .npl
  state_count()
  if .classic and cp.nr=.human then
    cp.draft=13 ! p=.human ! init_round()
    field "play" back color .col(p,1),.col(p,2),.col(p,3)
    drafty(p)
    else
    for j=1 to 13
      k=2+rnd(7) ! .state(cp.play(k),3)+=1
      next j
    end if
  next cp.nr
for i=1 to 42 ! button i text .state(i,3) ! next i
refresh on
end def
def draw_state(k,c)
dim x(11),y(11)
n=.surf(k,1)
fill color .col(c,1),.col(c,2),.col(c,3)
for i=1 to n
  p=.surf(k,i+1)
  x(i)=.node(p,1) ! y(i)=.node(p,2)
  next i
fill poly x,y count n ! draw poly x,y count n
end def
def state_count()
p=cp.nr ! k=1 ! cp.na=0
for i=1 to .ns
  if .state(i,2)<>p then continue
  k+=1 ! cp.play(k)=i ! cp.na+=.state(i,3)
  next i
cp.play(1)=k-1 ! return k-1
end def
def cont_count()
dim check(6) ! bonus=0
for i=2 to cp.ncp+1
  for k=1 to 6
    if cp.play(i)<=.cont(k,2) then
      check(k)+=1 ! break
      end if
    next k
  next i
for i=1 to 6
  if check(i)=.cont(i,4) then bonus+=.cont(i,3)
  next i
return bonus
end def
def disp_strength()
.sflag=1-.sflag
if .sflag then ! k=4 ! n$="Strength"
  else ! k=3 ! n$="Armies"
  end if
button("strength") text n$
for i=1 to .ns ! button i text floor(.state(i,k)) ! next i
a=human_play.lna ! if a and k=3 then sign_fight(a,1)
d=human_play.lnd ! if d and k=3 then sign_fight(d,2)
end def
def group1(on)
if on then
  field "draft" show ! field "attack" show ! field "move" show
  else
  field "draft" hide ! field "attack" hide ! field "move" hide
  end if
end def
def group2(on)
if on then
  button "less" show ! button "more" show ! button "okee" show
  button "troops" show ! button "maxtr" show
  else
  button "less" hide ! button "more" hide ! button "okee" hide
  button "troops" hide ! button "maxtr" hide
  end if
end def
def group3(on)
if on then
  button "datt" show ! button "att" show
  button "ddef" show ! button "def" show
  button "speed" show ! button "pause" show ! button "stop" show
  else
  button "datt" hide ! button "att" hide
  button "ddef" hide ! button "def" hide
  button "speed" hide ! button "pause" hide ! button "stop" hide
  end if
end def
def init_risk()
set toolbar off ! option base 1 ! randomize
set orientation landscape
graphics ! graphics clear .7,.7,.7 ! draw color 0,0,0
f$="risk_data" ! file f$ input .np,.ns,.nc ! .npl=6
dim .node(.np,2),.surf(.ns,12),.cont(.nc,4),.state(.ns,4)
dim .col(7,3),.cent(.ns,2),lines(4),.link(.ns,6),cp.play(44)
dim .cards(.npl),.ai(6,3)
.human=1+rnd(6)
' refresh off
for i=1 to 6 ! for j=1 to 3
  file f$ input .col(i,j)
  next j ! next i
for j=1 to 3 ! .col(7,j)=1 ! next j
for i=1 to .np
  file f$ input .node(i,1),.node(i,2)
  next i
for i=1 to .ns
  file f$ input .surf(i,1)
  for j=2 to .surf(i,1)+1
    file f$ input .surf(i,j)
    next j
  file f$ input .cent(i,1),.cent(i,2)
  button i text i at .cent(i,1),.cent(i,2) size 28,28
  next i
for i=1 to 6
  for j=1 to 3 ! file f$ input .cont(i,j) ! next j
  .cont(i,4)=.cont(i,2)-.cont(i,1)+1
  next i
draw dash 2
for i=1 to 26
  file f$ input k,lines(1),lines(2),lines(3),lines(4)
  draw line lines(1),lines(2) to lines(3),lines(4) 
next i
draw dash 0
for i=1 to .ns
  for j=1 to 6 ! file f$ input .link(i,j) ! next j
  next i
for i=1 to .ns
  file f$ input .state(i,1) ! .state(i,1)/=10
  .state(i,4)=0
  next i
for i=1 to 6
  .ai(i,1)=2+rnd(4) ! .ai(i,2)=.4+0.3*rnd(1) ! .ai(i,3)=3+rnd(3)
  next i
set buttons font size 70
button "cont" text chr$(10145) at 840,685 size 70,70
draw size 3 ! draw rect 695,605 to 805,755
field "draft" text "  Draft" at 700,610 size 100,40 RO
f_fld("draft","g") ! 'field "draft" hide
field "attack" text " Attack" at 700,660 size 100,40 RO
f_fld("attack","r") ! 'field "attack" hide
field "move" text "  Move" at 700,710 size 100,40 RO
f_fld("move","g") ! 'field "move" hide
field "play" text "Player" at  40,450 size 100,80
field "play" font name "MarkerFelt-Thin"
field "play" font size 30
sx=320 ! sy=645 ! sz=50
set buttons custom ! set buttons font size sz
button "less" text chr$(57915) at sx,sy size sz,sz
button "more" text chr$(57914) at sx+2.5*sz+20,sy size sz,sz
button "okee" text chr$(9989) at sx+2.5*sz+20,sy+sz+10 size sz,sz
set buttons font name "Georgia-Bold" ! set buttons font size 30
fill color .7,.7,1
button "troops" text "" at sx+sz+10,sy size 1.5*sz,sz
button "maxtr" text "" at sx+sz+10,sy+sz+10 size 1.5*sz,sz
button "cards" text "" at 580,705 size sz,sz
sx=10 ! sy=705 ! bw=75 ! bh=50
set buttons font name "MarkerFelt-Thin"
fill color .5,.5,.5
button "speed" text "Slow" at sx,sy size bw,bh
button "pause" text "Pause" at sx+bw+10,sy size bw,bh
button "stop" text "Start" at sx+2*bw+20,sy size bw,bh
button "strength" text "Armies" at 360,570 size 120,50
sx=10 ! sy=585
fill color .7,.7,1
set buttons font name "Georgia-Bold"
button "att" text "" at sx,sy+bh+10 size bw,bh
button "datt" text "" at sx,sy size bw,bh
button "def" text "" at sx+bw+10,sy+bh+10 size bw,bh
button "ddef" text "" at sx+bw+10,sy size bw,bh
draw font size 20 ! draw text "Cards" at 575,685
button "cont" hide ! button "cards" hide
button "strength" hide ! 
group1(0) ! group2(0) ! group3(0)
assign()   ' assign states and armies to players
end def
' table sorting function (option base 1 assumed)
' r = number of rows
' c = number of columns
' in(,) = table to be sorted
' out(,) = sorted table
' onc = column to be used for sorting
'
def tablesort (r,c,in(,),out(,),onc)
option sort descending
dim sortcol(r),index(r)
for i=1 to r ! sortcol(i)=in(i,onc) ! next i
sort sortcol as index
for i=1 to r ! for j=1 to c
  out(i,j)=in(index(i),j)
  next j ! next i
return
end def
