// LIFE.VDM  -  The Game of Life
//
// by Pauli Lindgren, 2000-11-06
//
// To use this macro:
//
// 1. Open Vedit with an empty buffer. Adjust the window size before starting
//    the macro. (Tip: use font that has as square character cell as possible.)
// 2. Start the macro.
// 3. Use cursor keys to move cursor and Space to toggle cell on/off.
// 4. When the patterns are ready, hit Enter to calculate one generation,
//    or R to animate next 100 generations. You can then continue to edit
//    the cells if you wish.
// 5. Press Q to quit/restart.

#30 = 2		// animation speed (delay), n/10 sec

:Start:
// Create the board
Config(PG_E_SYNTAX,0,LOCAL)	//Disable syntax highlighting
Buf_Empty(OK)
#3 = 2		// Line number
#9 = 0
#22 = 0		// number of generations
#10 = Win_Lines
#11 = Win_Cols
BOF
IT("Edit")
for (#1=1; #1<#10; #1++) {
  Ins_Newline
  IC('.', COUNT, #11)
}
BOF
Update()
Goto_Line(#10/2)
Goto_Col(#11/2)
Update()

// Read and interpret keypres
repeat(ALL) {
  #1 = Get_Key("Cursor = move, [Space] = set/clear cell, [Enter] = Run one generation, R = run, Q = Quit", STATLINE)
  if (#1=='q') {
    break
  }
  #2 = Cur_Col
  #21 = Cur_Line
  if (#1=='C'+'U'*256) {
    if(Cur_Line>2) {
      Line(-1)
      Goto_Col(#2)
    }
  }
  if (#1=='C'+'D'*256) {
    if(Cur_Line<#10) {
      Line(1)
      Goto_Col(#2)
    }
  }
  if (#1=='C'+'L'*256) {
    if(#2>1) {
      Char(-1)
    }
  }
  if (#1=='C'+'R'*256) {
    if(#2<#11) {
      Char(1)
    }
  }
  if (#1==' ') {
    if (Cur_Char=='.') {
      IC('O',OVERWRITE)
      Char(-1)
    } else {
      IC('.',OVERWRITE)
      Char(-1)
    }
  }
  if (#1=='r') {		// R = start animating cells
    #9 = 100
    Statline_Message("Running...")
    while (#9--) {
      Call("calculate")		// calculate one generation
      Update()
      Sleep(#30)
      if (Previous_Key(0) == 'q') {
	#9=0
      }
    }
    Goto_Line(#21)
    Goto_Col(#2)
  }
  if (#1=='R'+'T'*256) {	// Return 
    Call("calculate")		// calculate one generation
    Goto_Line(#21)
    Goto_Col(#2)
  }
  
  Update()
}

#1 = Get_Key("Play again (Y/N)? ", STATLINE)
if (#1=='y') {
  Goto Start
}

Return

// Calculate one generation

:calculate:
BOF
Line(1)
While (At_EOF == 0) {
  Search("|A",ERRBREAK)
  if (#3 != Cur_Line) {
    #3 = Cur_Line
    if (#3==2) { #5 = #10 } else { #5 = #3-1 }  // #5 = line above
    if (#3==#10) { #6 = 2 } else { #6 = #3+1 }  // #6 = line below
  }
  #4 = Cur_Col
  if (#4==1) { #7 = #11 } else { #7 = #4-1 }
  if (#4==#11) { #8 = 1 } else { #8 = #4+1 }
  Goto_Col(#7)
  IC(Cur_Char+1,OVERWRITE)
  Goto_Col(#8)
  IC(Cur_Char+1,OVERWRITE)
  Goto_Line(#5)
  Call("inc_3")
  Goto_Line(#6)
  Call("inc_3")
  Goto_Line(#3)
  Goto_Col(#4+1)
}
Goto_Line(2)
#20 = 0
do {
  if ((CC=='1') || (CC=='Q') || (CC=='R')) {
    IC('O',OVERWRITE)
    #20++
  } else {
    if (CC > '!') {
      IC('.',OVERWRITE)
    } else {
      char(1)
    }
  }
  Search("|!.",ERRBREAK)
} While (At_EOF == 0)
#22++
BOF
Del_Block(CP,EOL_pos)
IT("Gens:")
Num_Ins(#22,NOCR)
IT("  Cells:")
Num_Ins(#20,NOCR)
IT(" ")
Return

// increment values of 3 characters in a row

:inc_3:
Goto_Col(#7)
for (#1=0; #1<3; #1++) {
  IC(Cur_Char+1,OVERWRITE)
  if (At_EOL) {
    BOL
  }
}
Return