home *** CD-ROM | disk | FTP | other *** search
- * FOXLIFE.PRG The much implemented game of Life, invented by John Conway.
- * Based on anonymous C source from Internet, but modified greatly.
- * First ported to FoxPro by Tom Rombouts, Oct 2, 1991
- * Sixth major revision - Feb 1, 1993.
- * Possible enhancements:
- * Finish "edit pattern" code
- * Allow flat/circular toggle during session
- * Allow saving of each generation.
- * Possibly go to "one loop" calc/display method
- * Add saving partial game. Define menu at start, use
- * Optional command line arguments:
- PARAMETERS p_num_or_file, p_circular, p_char
- SET ESCAPE ON
- * Process command line arguments
- STORE .F. TO go_flag, file_flag
- DO CASE
- CASE TYPE("num_or_file")=="N"
- go_flag = .T.
- CASE TYPE("num_or_file")=="C"
- IF FILE(num_or_file)
- STORE .T. TO file_flag, go_flag
- ENDIF
- ENDCASE
-
- IF TYPE("p_circular")=="C"
- DO CASE
- CASE UPPER(p_circular)="CIRC"
- p_circular = .T.
- CASE UPPER(p_circular)="FLAT"
- p_circular = .F.
- ENDCASE
- ENDIF
-
- IF EMPTY(p_char)
- p_char = CHR(2) && Default to light smile face
- ENDIF
-
- SET TALK OFF
- SET COMPATIBLE OFF
- SET SCOREBOARD OFF
- SET CURSOR OFF
-
- ON ESCAPE STORE .T. TO stop_flag
- ON KEY LABEL F10 ACTIVATE POPUP lifeopts
-
- g_rows = SROWS() - 1 && Top line used for menu, messages
- g_cols = SCOLS()
-
- DECLARE acal[g_rows, g_cols]
- DECLARE adis[g_rows, g_cols]
- STORE 0 TO adis, acal
-
- STORE .F. TO menu_flag, stop_flag, quit_flag
-
- population = 0
- generation = 0
-
- * Global editing vars:
- STORE 0 To erow, ecol
-
- SET SYSMENU AUTOMATIC
-
- DEFINE PAD lifemenu OF _MSYSMENU PROMPT "Fox\<Life" KEY ALT+L, ""
- ON PAD lifemenu OF _MSYSMENU ACTIVATE POPUP lifeopts
-
- DEFINE POPUP lifeopts MARGIN RELATIVE SHADOW
- DEFINE BAR 1 OF lifeopts PROMPT "\<File"
- DEFINE BAR 2 OF lifeopts PROMPT "\<Edit"
- DEFINE BAR 3 OF lifeopts PROMPT "\<New"
- DEFINE BAR 4 OF lifeopts PROMPT "\<Save"
- DEFINE BAR 5 OF lifeopts PROMPT "\<About"
- DEFINE BAR 6 OF lifeopts PROMPT "\<Exit"
- ON SELECTION BAR 1 OF lifeopts DO FILE_GET IN FOXLIFE.PRG
- ON SELECTION BAR 2 OF lifeopts DO PATT_EDIT IN FOXLIFE.PRG
- ON SELECTION BAR 3 OF lifeopts DO INSTRUCT IN FOXLIFE.PRG
- ON SELECTION BAR 4 OF lifeopts DO FILE_SAVE IN FOXLIFE.PRG
- ON SELECTION BAR 5 OF lifeopts DO L_ABOUT IN FOXLIFE.PRG
- ON SELECTION BAR 6 OF lifeopts DO LIFE_EXIT IN FOXLIFE.PRG
-
-
- * Main sequence, cycle 'till two ESC chars:
- DO WHILE .T.
- CLEAR
- IF NOT go_flag
- num_or_file = INSTRUCT()
- ENDIF
- IF EMPTY(num_or_file)
- quit_flag = .T.
- EXIT
- ELSE
- STORE .F. TO stop_flag, quit_flag
- ENDIF
- IF TYPE("num_or_file")=="N"
- CLEAR
- DO FILL_RAND WITH num_or_file, g_rows, g_cols, p_char
- ENDIF
- IF TYPE("num_or_file")="C"
- CLEAR
- DO PATT_LOAD WITH num_or_file, g_rows, g_cols, p_char
- ENDIF
- DO WHILE .T. && This simultates a do{...}while construct:
- m.generation = (m.generation + 1)
- acal = 0 && Zero out calculation array
- IF m.p_circular
- DO CAL_EDGE_CIRC WITH m.g_rows, m.g_cols
- ELSE
- DO CAL_EDGE_FLAT WITH m.g_rows, m.g_cols
- ENDIF
- DO CAL_CENTER WITH m.g_rows - 1, m.g_cols - 1
- DO SHOW_EM WITH m.g_rows, m.g_cols, m.p_char
- WAIT WINDOW NOWAIT "Cycle: " + LTRIM(STR(m.generation)) + ;
- " Cells: " + LTRIM(STR(m.population))
- =ACOPY("acal", "adis")
- IF (m.population == 0) OR stop_flag
- EXIT
- ENDIF
- ENDDO
- IF quit_flag
- EXIT
- ENDIF
- ENDDO
- DO PATT_SAVE WITH "lastlife.dat", m.g_rows, m.g_cols
-
- DEACTIVATE MENU mainmenu
- RELEASE MENU mainmenu
- SET SYSMENU TO DEFAULT
- ON ESCAPE
- ON KEY LABEL F10
- CLEAR
- WAIT WINDOW NOWAIT "That's all, folks!"
- SET CURSOR ON
-
-
- FUNCTION INSTRUCT && Print instructions, one screen's worth:
- PRIVATE user_val, scr_temp
- SAVE SCREEN TO scr_temp
- CLEAR
- SET CURSOR ON
- STORE SPACE(12) TO user_val
-
- @ 1, 0 SAY " The game of Life by John Conroy"
-
- @ 3, 0 SAY " If started with a number, a random pattern starts the game."
- @ 4, 0 SAY " If started with a file name, will load game based on data "
- @ 5, 0 SAY " in that file. "
-
- @ 7, 0 SAY " F10 will activate the menu. Hit ESC to bail out."
-
- @ 9, 0 SAY " Enter number of cells or data file name, or hit CR: " ;
- GET user_val
- READ
- SET CURSOR OFF
- IF EMPTY( user_val )
- RESTORE SCREEN FROM scr_temp
- ELSE
- CLEAR
- ENDIF
- RELEASE scr_temp
- IF VAL(user_val) > 0
- RETURN VAL(user_val)
- ELSE
- RETURN user_val
- ENDIF
-
- FUNCTION FILL_RAND
- * Refill display array with random values.
- PARAMETER number, p_rows, p_cols, p_char
- PRIVATE i, row, col, seed, rnum
- * Reset relevant globals:
- STORE 0 TO population, generation
- * Zero out display array:
- STORE 0 TO adis
- =RAND(-1)
- WAIT WINDOW NOWAIT "Generating random pattern...."
- FOR m.i = 1 TO m.number
- m.rnum = RAND() * 10000
- m.row = MOD(m.rnum, m.p_rows)
- m.col = MOD( INT(m.rnum/m.p_rows), m.p_cols)
- adis[m.row + 1, m.col + 1] = 1 && Put in a cell
- population = m.population + 1
- @ m.row, m.col SAY m.p_char
- ENDFOR && m.number loop
- WAIT CLEAR
- RETURN
-
-
- FUNCTION CAL_EDGE_CIRC
- * Re-calculate the next generation based on the display array.
- * Fewer loops (and more code) is done to maximize re-calc speed.
- PARAMETERS p_rows, p_cols
- PRIVATE crow, ccol, dncol, upcol, lfcol, rtcol
-
- * Take care of the four corners, assume "circular" screen:
- IF NOT EMPTY(adis[ 1, 1])
- STORE acal[m.p_rows, m.p_cols] + 1 TO acal[m.p_rows, m.p_cols]
- STORE acal[m.p_rows, 1] + 1 TO acal[m.p_rows, 1]
- STORE acal[m.p_rows, 2] + 1 TO acal[m.p_rows, 2]
- STORE acal[ 1,m.p_cols] + 1 TO acal[ 1,m.p_cols]
- STORE acal[ 1, 2] + 1 TO acal[ 1, 2]
- STORE acal[ 2,m.p_cols] + 1 TO acal[ 2,m.p_cols]
- STORE acal[ 2, 1] + 1 TO acal[ 2, 1]
- STORE acal[ 2, 2] + 1 TO acal[ 2, 2]
- ENDIF
-
- IF NOT EMPTY(adis[ 1, m.p_cols])
- STORE acal[m.p_rows, m.p_cols - 1] + 1 TO acal[m.p_rows, m.p_cols - 1]
- STORE acal[m.p_rows, m.p_cols] + 1 TO acal[m.p_rows, m.p_cols]
- STORE acal[m.p_rows, 1] + 1 TO acal[m.p_rows, 1]
- STORE acal[ 1, m.p_cols - 1] + 1 TO acal[ 1, m.p_cols - 1]
- STORE acal[ 1, 1] + 1 TO acal[ 1, 1]
- STORE acal[ 2, m.p_cols - 1] + 1 TO acal[ 2, m.p_cols - 1]
- STORE acal[ 2, m.p_cols] + 1 TO acal[ 2, m.p_cols]
- STORE acal[ 2, 1] + 1 TO acal[ 2, 1]
- ENDIF
-
- IF NOT EMPTY(adis[m.p_rows, m.p_cols])
- STORE acal[m.p_rows - 1, m.p_cols - 1] + 1 TO ;
- acal[m.p_rows - 1, m.p_cols - 1]
- STORE acal[m.p_rows - 1, m.p_cols] + 1 TO acal[m.p_rows - 1, m.p_cols]
- STORE acal[m.p_rows - 1, 1] + 1 TO acal[m.p_rows - 1, 1]
- STORE acal[m.p_rows, m.p_cols - 1] + 1 TO acal[m.p_rows, m.p_cols - 1]
- STORE acal[m.p_rows, 1] + 1 TO acal[m.p_rows, 1]
- STORE acal[ 1, m.p_cols - 1] + 1 TO acal[ 1, m.p_cols - 1]
- STORE acal[ 1, m.p_cols] + 1 TO acal[ 1, m.p_cols]
- STORE acal[ 1, 1] + 1 TO acal[ 1, 1]
- ENDIF
-
- IF NOT EMPTY(adis[m.p_rows, 1])
- STORE acal[m.p_rows - 1, m.p_cols] + 1 TO ;
- acal[m.p_rows - 1, m.p_cols]
- STORE acal[m.p_rows - 1, 1] + 1 TO acal[m.p_rows - 1, 1]
- STORE acal[m.p_rows - 1, 2] + 1 TO acal[m.p_rows - 1, 2]
- STORE acal[m.p_rows, m.p_cols] + 1 TO acal[m.p_rows, m.p_cols]
- STORE acal[m.p_rows, 2] + 1 TO acal[m.p_rows, 2]
- STORE acal[ 1, m.p_cols] + 1 TO acal[ 1, m.p_cols]
- STORE acal[ 1, 1] + 1 TO acal[ 1, 1]
- STORE acal[ 1, 2] + 1 TO acal[ 1, 2]
- ENDIF
-
- * Re-calc the leftmost and rightmost columns:
- FOR crow = 2 TO (m.p_rows - 1)
- IF NOT EMPTY(adis[m.crow, 1])
- STORE acal[m.crow - 1, m.p_cols] + 1 TO acal[m.crow - 1, m.p_cols]
- STORE acal[m.crow - 1, 1] + 1 TO acal[m.crow - 1, 1]
- STORE acal[m.crow - 1, 2] + 1 TO acal[m.crow - 1, 2]
- STORE acal[m.crow, m.p_cols] + 1 TO acal[m.crow, m.p_cols]
- STORE acal[m.crow, 2] + 1 TO acal[m.crow, 2]
- STORE acal[m.crow + 1, m.p_cols] + 1 TO acal[m.crow + 1, m.p_cols]
- STORE acal[m.crow + 1, 1] + 1 TO acal[m.crow + 1, 1]
- STORE acal[m.crow + 1, 2] + 1 TO acal[m.crow + 1, 2]
- ENDIF
- IF NOT EMPTY(adis[m.crow, m.p_cols])
- STORE acal[m.crow - 1, m.p_cols - 1] + 1 TO acal[m.crow - 1, m.p_cols - 1]
- STORE acal[m.crow - 1, m.p_cols] + 1 TO acal[m.crow - 1, m.p_cols]
- STORE acal[m.crow - 1, 1] + 1 TO acal[m.crow - 1, 1]
- STORE acal[m.crow, m.p_cols - 1] + 1 TO acal[m.crow, m.p_cols - 1]
- STORE acal[m.crow, 1] + 1 TO acal[m.crow, 1]
- STORE acal[m.crow + 1, m.p_cols - 1] + 1 TO ;
- acal[m.crow + 1, m.p_cols - 1]
- STORE acal[m.crow + 1, m.p_cols] + 1 TO acal[m.crow + 1, m.p_cols]
- STORE acal[m.crow + 1, 1] + 1 TO acal[m.crow + 1, 1]
- ENDIF
- ENDFOR
-
- * Re-calc the top and bottom rows:
- FOR ccol = 2 TO m.p_cols - 1
- IF NOT EMPTY(adis[1, m.ccol])
- STORE acal[m.p_rows, m.ccol - 1] + 1 TO acal[m.p_rows, m.ccol - 1]
- STORE acal[m.p_rows, m.ccol ] + 1 TO acal[m.p_rows, m.ccol ]
- STORE acal[m.p_rows, m.ccol + 1] + 1 TO acal[m.p_rows, m.ccol + 1]
- STORE acal[ 1, m.ccol - 1] + 1 TO acal[ 1, m.ccol - 1]
- STORE acal[ 1, m.ccol + 1] + 1 TO acal[ 1, m.ccol + 1]
- STORE acal[ 2, m.ccol - 1] + 1 TO acal[ 2, m.ccol - 1]
- STORE acal[ 2, m.ccol ] + 1 TO acal[ 2, m.ccol ]
- STORE acal[ 2, m.ccol + 1] + 1 TO acal[ 2, m.ccol + 1]
- ENDIF
- IF NOT EMPTY(adis[m.p_rows, m.ccol])
- STORE acal[m.p_rows - 1, m.ccol - 1] + 1 TO ;
- acal[m.p_rows - 1, m.ccol - 1]
- STORE acal[m.p_rows - 1, m.ccol ] + 1 TO ;
- acal[m.p_rows - 1, m.ccol]
- STORE acal[m.p_rows - 1, m.ccol + 1] + 1 TO ;
- acal[m.p_rows - 1, m.ccol + 1]
- STORE acal[m.p_rows, m.ccol - 1] + 1 TO acal[m.p_rows, m.ccol - 1]
- STORE acal[m.p_rows, m.ccol + 1] + 1 TO acal[m.p_rows, m.ccol + 1]
- STORE acal[ 1, m.ccol - 1] + 1 TO acal[ 1, m.ccol - 1]
- STORE acal[ 1, m.ccol ] + 1 TO acal[ 1, m.ccol]
- STORE acal[ 1, m.ccol + 1] + 1 TO acal[ 1, m.ccol + 1]
- ENDIF
- ENDFOR
- RETURN && CAL_EDGE_CIRC
-
-
- FUNCTION CAL_EDGE_FLAT
- * Re-calculate the next generation based on the display array.
- * Fewer loops (and more code) is done to maximize re-calc speed.
- PARAMETERS p_rows, p_cols
- PRIVATE crow, ccol, dncol, upcol, lfcol, rtcol
-
- * Take care of the four corners, assume "flat" screen:
- IF NOT EMPTY(adis[ 1, 1])
- STORE acal[ 1, 2] + 1 TO acal[ 1, 2]
- STORE acal[ 2, 1] + 1 TO acal[ 2, 1]
- STORE acal[ 2, 2] + 1 TO acal[ 2, 2]
- ENDIF
-
- IF NOT EMPTY(adis[ 1, m.p_cols])
- STORE acal[ 1, m.p_cols - 1] + 1 TO acal[ 1, m.p_cols - 1]
- STORE acal[ 2, m.p_cols - 1] + 1 TO acal[ 2, m.p_cols - 1]
- STORE acal[ 2, m.p_cols] + 1 TO acal[ 2, m.p_cols]
- ENDIF
-
- IF NOT EMPTY(adis[m.p_rows, m.p_cols])
- STORE acal[m.p_rows - 1, m.p_cols - 1] + 1 TO ;
- acal[m.p_rows - 1, m.p_cols - 1]
- STORE acal[m.p_rows - 1, m.p_cols] + 1 TO acal[m.p_rows - 1, m.p_cols]
- STORE acal[m.p_rows, m.p_cols - 1] + 1 TO acal[m.p_rows, m.p_cols - 1]
- ENDIF
-
- IF NOT EMPTY(adis[m.p_rows, 1])
- STORE acal[m.p_rows - 1, 1] + 1 TO acal[m.p_rows - 1, 1]
- STORE acal[m.p_rows - 1, 2] + 1 TO acal[m.p_rows - 1, 2]
- STORE acal[m.p_rows, 2] + 1 TO acal[m.p_rows, 2]
- ENDIF
-
- * Re-calc the leftmost and rightmost columns:
- FOR crow = 2 TO (m.p_rows - 1)
- IF NOT EMPTY(adis[m.crow, 1])
- STORE acal[m.crow - 1, 1] + 1 TO acal[m.crow - 1, 1]
- STORE acal[m.crow - 1, 2] + 1 TO acal[m.crow - 1, 2]
- STORE acal[m.crow, 2] + 1 TO acal[m.crow, 2]
- STORE acal[m.crow + 1, 1] + 1 TO acal[m.crow + 1, 1]
- STORE acal[m.crow + 1, 2] + 1 TO acal[m.crow + 1, 2]
- ENDIF
- IF NOT EMPTY(adis[m.crow, m.p_cols])
- STORE acal[m.crow - 1, m.p_cols - 1] + 1 TO acal[m.crow - 1, m.p_cols - 1]
- STORE acal[m.crow - 1, m.p_cols] + 1 TO acal[m.crow - 1, m.p_cols]
- STORE acal[m.crow, m.p_cols - 1] + 1 TO acal[m.crow, m.p_cols - 1]
- STORE acal[m.crow + 1, m.p_cols - 1] + 1 TO ;
- acal[m.crow + 1, m.p_cols - 1]
- STORE acal[m.crow + 1, m.p_cols] + 1 TO acal[m.crow + 1, m.p_cols]
- ENDIF
- ENDFOR
-
- * Re-calc the top and bottom rows:
- FOR ccol = 2 TO m.p_cols - 1
- IF NOT EMPTY(adis[1, m.ccol])
- STORE acal[ 1, m.ccol - 1] + 1 TO acal[ 1, m.ccol - 1]
- STORE acal[ 1, m.ccol + 1] + 1 TO acal[ 1, m.ccol + 1]
- STORE acal[ 2, m.ccol - 1] + 1 TO acal[ 2, m.ccol - 1]
- STORE acal[ 2, m.ccol ] + 1 TO acal[ 2, m.ccol ]
- STORE acal[ 2, m.ccol + 1] + 1 TO acal[ 2, m.ccol + 1]
- ENDIF
- IF NOT EMPTY(adis[m.p_rows, m.ccol])
- STORE acal[m.p_rows - 1, m.ccol - 1] + 1 TO ;
- acal[m.p_rows - 1, m.ccol - 1]
- STORE acal[m.p_rows - 1, m.ccol ] + 1 TO ;
- acal[m.p_rows - 1, m.ccol]
- STORE acal[m.p_rows - 1, m.ccol + 1] + 1 TO ;
- acal[m.p_rows - 1, m.ccol + 1]
- STORE acal[m.p_rows, m.ccol - 1] + 1 TO acal[m.p_rows, m.ccol - 1]
- STORE acal[m.p_rows, m.ccol + 1] + 1 TO acal[m.p_rows, m.ccol + 1]
- ENDIF
- ENDFOR
- RETURN && CAL_EDGE_FLAT
-
-
-
-
-
-
-
-
-
-
- FUNCTION CAL_EDGE_FLAT
- * TWR - non-circular screen!
- * Note: all cells off screen are considered "dead"
- * Take care of the four corners, non-circular screen:
- PARAMETERS p_rows, p_cols
- acal[ 1, 1] = adis[ 1, 2] + adis[ 2, 2] + adis[ 2, 1]
- acal[ 1,80] = adis[ 1,79] + adis[ 2,79] + adis[ 2,80]
- acal[24, 1] = adis[24, 2] + adis[23, 2] + adis[23, 1]
- acal[24,80] = adis[24,79] + adis[23,79] + adis[23,80]
-
- * Re-calc the left column:
- FOR crow = 2 TO 23
- uprow = (m.crow - 1)
- dnrow = (m.crow + 1)
- acal[m.crow, 1] = adis[m.uprow, 1] + adis[m.uprow, 2] + ;
- adis[m.crow, 2] + adis[m.dnrow, 1] + adis[m.dnrow, 2]
- ENDFOR
-
- * Re-calc the right column:
- FOR crow = 2 TO 23
- uprow = (crow - 1)
- dnrow = (crow + 1)
- acal[crow, 80] = adis[uprow, 79] + adis[uprow, 80] + ;
- adis[ crow, 79] + adis[dnrow, 79] + adis[dnrow, 80]
- ENDFOR
-
- * Re-calc the top row:
- FOR ccol = 2 TO 79
- lfcol = (ccol - 1)
- rtcol = (ccol + 1)
- acal[ 1, ccol] = adis[ 1, lfcol] + adis[ 1, rtcol] + ;
- adis[ 2, lfcol] + adis[ 2, ccol] + adis[ 2, rtcol]
- ENDFOR
-
- * Re-calc the bottom row:
- FOR ccol = 2 TO 79
- lfcol = (ccol - 1)
- rtcol = (ccol + 1)
- acal[24, ccol] = adis[23, lfcol] + adis[23, ccol] + adis[23, rtcol] + ;
- adis[24, lfcol] + adis[24, rtcol]
- ENDFOR
-
- RETURN && CAL_EDGE_FLAT
-
-
- FUNCTION CAL_CENTER
- * Re-calculate the non-edges (center) of the array:
- PARAMETERS p_rows, p_cols
- FOR crow = 2 TO m.p_rows
- FOR ccol = 2 TO m.p_cols
- IF NOT EMPTY(adis[m.crow, m.ccol])
- uprow = (m.crow - 1)
- dnrow = (m.crow + 1)
- lfcol = (m.ccol - 1)
- rtcol = (m.ccol + 1)
- * Update the eight cells around it:
- STORE acal[m.uprow, m.lfcol] + 1 TO acal[m.uprow, m.lfcol]
- STORE acal[m.uprow, m.ccol] + 1 TO acal[m.uprow, m.ccol]
- STORE acal[m.uprow, m.rtcol] + 1 TO acal[m.uprow, m.rtcol]
- STORE acal[m.crow, m.lfcol] + 1 TO acal[m.crow, m.lfcol]
- STORE acal[m.crow, m.rtcol] + 1 TO acal[m.crow, m.rtcol]
- STORE acal[m.dnrow, m.lfcol] + 1 TO acal[m.dnrow, m.lfcol]
- STORE acal[m.dnrow, m.ccol] + 1 TO acal[m.dnrow, m.ccol]
- STORE acal[m.dnrow, m.rtcol] + 1 TO acal[m.dnrow, m.rtcol]
- ENDIF
- ENDFOR
- ENDFOR
- RETURN
-
-
- FUNCTION SHOW_EM
- * Determine new status and display each cell:
- * Assumes display starts at 1, 0
- PARAMETERS p_rows, p_cols, p_char
- STORE 0 TO population
- FOR crow = 1 TO m.p_rows
- @ m.crow, 0 && Clear current row
- FOR ccol = 1 TO m.p_cols
- * Preserve living cell if 2 or 3 neighbors:
- cur_cell = acal[m.crow, m.ccol] && attempted speedup
- IF cur_cell == 3
- acal[m.crow, m.ccol] = 1
- ELSE
- IF cur_cell == 2 AND adis[m.crow, m.ccol] == 1
- acal[m.crow, m.ccol] = 1
- ELSE
- acal[m.crow, m.ccol] = 0
- ENDIF
- ENDIF
- IF acal[m.crow, m.ccol] > 0
- m.population = (m.population + 1)
- @ m.crow, (m.ccol - 1) SAY m.p_char
- ENDIF
- ENDFOR
- ENDFOR
-
- RETURN .T. && SHOW_EM
-
-
- FUNCTION PATT_SAVE
- PARAMETER savefile, p_rows, p_cols
- * Write out 4000 byte text file. Overwrites file.
- * This uses a somewhat slow, but reliable method.
- PRIVATE handle, srow, scol
- handle = FCREATE( savefile )
- IF handle < 1
- WAIT WINDOW "Error creating file: " + savefile
- RETURN .F.
- ENDIF
- FOR srow = 1 TO p_rows
- FOR scol = 1 TO p_cols
- IF adis[srow, scol] > 0
- =FWRITE( handle, "X" )
- ELSE
- =FWRITE( handle, " " )
- ENDIF
- ENDFOR
- =FWRITE( handle, CHR(13) + CHR(10) )
- ENDFOR
- srow = FCLOSE( handle )
- IF NOT srow
- WAIT WINDOW "Error closing file: " + savefile
- RETURN .F.
- ENDIF
- RETURN .T.
-
-
- FUNCTION FILE_GET
- PRIVATE newfile
- newfile = GETFILE("DAT", "New pattern: ")
- IF EMPTY(newfile)
- RETURN
- ELSE
- DO PATT_LOAD WITH newfile, g_rows, g_cols, p_char
- ENDIF
- RETURN
-
-
- FUNCTION PATT_LOAD
- PARAMETERS data_file, p_rows, p_cols, p_char
- * Load array adis[m.p_rows X m.p_cols] from file.
- * Space considered empty, any other char as life.
- PRIVATE handle, row, col, cur_line
- STORE 0 TO population, generation, acal, adis
- handle = FOPEN( data_file ) && no arg, read only, buffered
- IF NOT handle > 0
- RETURN
- ENDIF
-
- * TWR - this line may not be correct!
- FOR row = 1 TO m.p_rows
- cur_line = FGETS( handle )
- IF FEOF( handle )
- EXIT
- ENDIF
- WAIT WINDOW NOWAIT "Reading in row " + LTRIM(STR(m.row))
- IF LEFT(LTRIM(m.cur_line), 1) = "*"
- row = (m.row - 1)
- LOOP
- ENDIF
- width = MIN(LEN( cur_line ), m.p_cols)
- FOR col = 1 TO width
- IF SUBSTR(cur_line, col, 1) = "*"
- EXIT
- ENDIF
- IF SUBSTR( cur_line, col, 1 ) != " "
- adis[row, col] = 1
- m.population = (m.population + 1)
- @ row, col SAY m.p_char
- ELSE
- @ row, col SAY " "
- ENDIF
- ENDFOR
- ENDFOR
- =FCLOSE( handle )
- WAIT CLEAR
- RETURN
-
-
- FUNCTION PATT_EDIT
- * Simulate editing of pattern on screen
- * Uses globals for speed
- WAIT WINDOW "Pattern editing not completed - any key to continue"
- RETURN && early exit
- PRIVATE ekey
- @ 24, 0 SAY "Edit mode Arrow keys move - spacebar toggles - ESC or CR to end"
- CLEAR TYPEAHEAD
- DO WHILE .T.
- ekey = INKEY(0)
- DO CASE
- CASE ekey == 13 OR ekey == 27 && Enter or ESC
- @ erow, ecol SAY adis[ erow + 1, ecol + 1 ]
- EXIT
- CASE ekey == 32 && Spacebar
- adis[erow + 1, ecol + 1] = IIF( adis[erow + 1, ecol + 1] > 0, ;
- 0, 1 )
- @ erow, ecol SAY IIF(adis[erow + 1, ecol + 1] > 0, CHR(2), " " )
- CASE ekey == 5 && Up arrow
- IF erow > 0
- erow = erow - 1
- @ erow + 1, ecol SAY IIF(adis[erow + 1, ecol + 1] > 0, CHR(2), " ")
- @ erow, ecol SAY "" GET (adis[erow + 1, ecol + 1])
- ENDIF
- CASE ekey == 4 && Right arrow
- IF ecol < 79
- ecol = ecol + 1
- @ erow, ecol - 1 SAY adis[ erow + 1, ecol + 1 ]
- @ erow, ecol SAY "" GET adis[ erow + 1, ecol + 1 ]
- ENDIF
- CASE ekey == 24 && Down arrow
- IF erow > 24
- erow = erow + 1
- @ erow - 1, ecol SAY adis[ erow + 1, ecol + 1 ]
- @ erow, ecol SAY "" GET adis[ erow + 1, ecol + 1 ]
- ENDIF
- CASE ekey == 19 && Left arrow
- IF ecol > 0
- ecol = ecol - 1
- @ erow, ecol - 1 SAY adis[ erow + 1, ecol + 1 ]
- @ erow, ecol SAY "" GET adis[ erow + 1, ecol + 1 ]
- ENDIF
- ENDCASE
- ENDDO
- RETURN .T.
-
-
- FUNCTION L_ABOUT
- PRIVATE idaho
- DEFINE WINDOW about FROM 1, 20 TO 9, 55
- ACTIVATE WINDOW about
- @ 1, 1 SAY " The game of Life "
- @ 2, 1 SAY " Invented by John Conway, 1970 "
- @ 3, 1 SAY " FoxPro version by Tom Rombouts "
- @ 4, 1 SAY " "
- @ 5, 1 SAY " Press any key to continue... "
- idaho = INKEY(0)
- DEACTIVATE WINDOW about
- RELEASE WINDOW about
- RETURN
-
-
- FUNCTION FILE_SAVE
- PRIVATE savefile
- savefile = PUTFILE("Save game as: ", SPACE(12), "DAT")
- IF EMPTY( savefile )
- RETURN
- ELSE
- DO PATT_SAVE WITH savefile
- ENDIF
- RETURN
-
-
- FUNCTION LIFE_EXIT
- * Do clean up
- STORE .T. TO stop_flag, exit_flag
- RETURN
-
- * EOP: FOXLIFE.PRG
-
-
- * Function used during debugging:
- FUNCTION SHOW_ACAL
- FOR x = 1 TO 24
- FOR y = 1 TO 80
- @ x, y - 1 SAY LTRIM(STR(acal[m.x, m.y]))
- ENDFOR
- ENDFOR
- WAIT WINDOW "Press any key..."
- RETURN
-