Jump to content

  • Log In with Google      Sign In   
  • Create Account

Beals Software



Severely unproductive

Posted by , in 1GAM, Scribe 26 March 2013 - - - - - - · 639 views

Well, the last 24 days have not been very productive at all. I attempted to implement nested conditionals and loops and thought I had them in and working that night. They were...kind of working; however other normal scripts were now not working properly. As my server had died the day after my last post, I was unable to commit to source control. So I did the next best thing: I just made the changes without making backups (okay, technically I had made a backup: I copied the entire file into Notepad++, but didn't save it, so when my laptop locked up later that night, I lost the "backup".)

At this point I was basically back to square one, so I decided to take a couple days off (after I spent a bit of time working on it; trying to clear my head of it and come back to it with a fresh mind.) Things have been super hectic in life altogether: my office just closed so I am working from home now (just want to clarify: as a remote employee, I didn't lose my job), getting ready for the baby (coming in June), and making room for a family member to move in within a month or two. None of this is bad news, it just has made things quite hectic.

I have managed to get Scribe working properly now though (so far anyway; I've been testing it all evening and haven't had any problems.) I'm going to start porting SAGE from Xna to MonoGame tomorrow, which will include lengthy tests of the scripting engine, so we'll see how things go. I'm very hopeful that it will work continue working properly. I've attached all of the example scripts I've used for testing as well as the new documentation. Once I've run the library through the ringer I'll put it up somewhere for download.

I've brought on some help that will be filling a sort of generic project manager role. Basically he is going to keep projects moving, make sure everyone is doing their job, help flesh out ideas and maybe some other areas (we haven't fully discussed his full role yet; these are just what he has been doing.) He's doing an amazing job so far; fleshing out some projects for our first couple projects (we're having a meeting tomorrow about The Mysterious Life of Aaron James) and has possibly found an artist. Anyway, I'm not sure when he'll end up showing his face on here, but I'm sure he will eventually.

Sadly my March project for 1GaM hasn't budged, so I'm not sure that I'll be finishing it. I'm going to flesh things out tonight, do a design document of sorts and then I'll decide from there whether or not it is feasible. If it is not I may just attempt a different game for this month. I'm off to start on this now.

Attached Files




1GAM March and new Scribe feature: calling labels by variable

Posted by , in Scribe 02 March 2013 - - - - - - · 609 views

So, I started working on my March game for One Game a Month which is going to use both my GameJolt library and Scribe. It is going to be a roguelike (coincidentally; I had decided to make it a roguelike halfway through February, before they had decided on the theme lol) based on a short story I have (almost) finished. The story has a post apocalyptic setting and revolves around a young man named Henry on a quest to find his dying father some help.

Here is a shot using placeholder art:
Attached Image
This is a shot of the starting map: the bunker you and your father are living in. You wake up and the power is out; you check on your father (top right bed) and he has you go check on the generator (which is obviously not in working condition, seeing as how the power is out.)

I ran into some issues with Scribe here, mainly due to the lack of support for nested conditionals and loops. I was going to try to implement them (which I've already tried before), but I decided to take a whack at implementing another feature: calling labels using the label name stored in a variable. This kind of simulates a switch statement. Here is an example:
 
if @fatherState == null
	@fatherState = 0
	
goto @fatherState
 
0:
LockInput
Say "Henry, can you go check on the generator?"
yield @someoneIsSpeaking == true
Say "Don't forget that the password is 34719"
@fatherState = 1
yield @someoneIsSpeaking == true
UnlockInput
goto exit
 
1:
LockInput
Say "I thought you were checking on the generator?"
yield @someoneIsSpeaking == true
Say "Remember, the password is 34719"
yield @someoneIsSpeaking == true
UnlockInput
goto exit
	
exit:
// Since we cannot nest conditionals or loops
// we use a label.

So, the first run of the script fatherState will be null, so we set it to 0, then we jump to the label 0, run through it's commands, set the state to 1, and then jump to exit. Every run after that we will just jump straight to 1, run our commands, and then jump to exit (I know that it seems kind of redundant to put the "goto exit" right above the label since we would fall through to exit, but this way we are all set if we need to add more states.)

As a side note, this is what I would consider proper use of the yield command. When I call the Say command it creates a label, positions it at the top of the screen, makes it visible, sets the variable someoneIsSpeaking to true, and then creates a task that will set someoneIsSpeaking to false and hide the label in 3 seconds. Remember that yield is the opposite of while: it loops until its condition is false and it is best to use the condition that will cause the loop to break if the variable isn't updated. This is why I check against true; if the variable isn't set it will be null and if it is ever set, it will eventually be set to false. If we used "yield @someoneIsSpeaking != false" and the variable is never set, we'll end up with an infinite loop.

Anyway, you can now call labels using literal values or variables (obviously they have to contain a valid name.) I'm going to take another whack at implementing nested conditionals and loops, but for now this should get me by. For now I am off to try to get some more work done on the story.

[edit]
I decided to sit down and focus on nested conditionals...thirty minutes later and viola, Scribe now supports them (testing nested loops at the moment.) Here's an example script:
 
@var1 = 10
@var2 = 3
@var3 = 10
 
if @var1 > 4
	if @var2 > 5
		if @var3 > 6
			Console.WriteLine 'All are true'
		else
			Console.WriteLine 'The first two are true'
	elseif @var3 > 6
		Console.WriteLine 'Only the first and third are true'
	else
		Console.WriteLine 'Only the first is true'
elseif @var2 > 5
	if @var3 > 6
		Console.WriteLine 'The last two are true'
	else
		Console.WriteLine 'Only the second is true'
elseif @var3 > 6
	Console.WriteLine 'Ony the third is true'
else
	Console.WriteLine 'None are true'


[edit]
And now nested loops are in:
 
@index1 = 0
 
while @index1 < 3
	@index2 = 0
	Console.WriteLine 'Index1:' @index1
	
	while @index2 < 3
		@index3 = 0
		Console.WriteLine '    Index2:' @index2
		
		while @index3 < 3
			Console.WriteLine '        Index3:' @index3
			
			@index3 += 1
		@index2 += 1
	@index1 += 1

Getting both to nest properly took a bit of work now and will be a bit of work to refactor, but it is definitely a feature that was needed. Now to verify that mixed nesting works properly.


Scribe scripting library

Posted by , in Scribe 28 February 2013 - - - - - - · 512 views

One of the projects I have always wanted to do is create a scripting language, but I have always failed horribly. My most recent attempt was kind of a mix of success and failure. The initial goals were to create a high level syntax (something similar to BASIC) and create a low level language (basically straight op codes; kind of like a simplified assembly.)
I meant to start out implementing the low level version first, but this didn't pan out how I wanted to and I ended up with a more BASIC-esque language. However it is working wonderfully, so I kept it and dubbed it Scribe 1.0. Currently it supports most of your basic features:
- Arithmetic operations
- Conditionals (if, elseif, else)
- Loops (loop, yield)
- Variables (booleans, strings, and numbers)
- Commands
- Labels

I achieved many of the goals that I wanted to, so I'm quite happy: it runs properly on both Windows and Android (and should hopefully , it runs decently (I haven't done any optimizations yet), it doesn't have any built in commands (so no sandboxing needed), and it is easily extendable (I am creating some packages that come with the library that provide some core functionality; they have to explicitly be registered though.)

I'm planning on eventually open-sourcing it, but I want to get it a little more stable and clean it up some first. Anyway, here is Tic Tac Toe written with Scribe and using the Console package:
// Initialize the board
clear_board:
@board11 = ' '
@board12 = ' '
@board13 = ' '
@board21 = ' '
@board22 = ' '
@board23 = ' '
@board31 = ' '
@board32 = ' '
@board33 = ' '
@playerToken = 'x'
@errorMessage = ''

game_loop:
Console.Clear
Console.SetTextColor Red
Console.WriteLine @errorMessage

Console.SetTextColor White
Console.WriteLine ' 1 2 3'
Console.WriteLine ' 1 ' @board11 | @board21 | @board31
Console.WriteLine ' -+-+-'
Console.WriteLine ' 2 ' @board12 | @board22 | @board32
Console.WriteLine ' -+-+-'
Console.WriteLine ' 3 ' @board13 | @board23 | @board33
Console.WriteLine ''

// Check win conditions
if @board11 != ' ' && @board11 == @board21 && @board11 == @board31
// Horizontal row 1
@winner = @board11
goto game_over
elseif @board12 != ' ' && @board12 == @board22 && @board12 == @board32
// Horizontal row 2
@winner = @board12
goto game_over
elseif @board13 != ' ' && @board13 == @board23 && @board13 == @board33
// Horizontal row 3
@winner = @board13
goto game_over
elseif @board11 != ' ' && @board11 == @board12 && @board11 == @board13
// Vertical column 1
@winner = @board11
goto game_over
elseif @board21 != ' ' && @board21 == @board22 && @board21 == @board23
// Vertical column 2
@winner = @board21
goto game_over
elseif @board31 != ' ' && @board31 == @board32 && @board31 == @board33
// Vertical column 3
@winner = @board31
goto game_over
elseif @board11 != ' ' && @board11 == @board22 && @board11 == @board33
// Diagonal top left to bottom right
@winner = @board11
goto game_over
elseif @board31 != ' ' && @board31 == @board22 && @board31 == @board13
// Diagonal top right to bottom left
@winner = @board31
goto game_over

if @board11 != ' ' && @board12 != ' ' && @board13 != ' ' && @board21 != ' ' && @board22 != ' ' && @board23 != ' ' && @board31 != ' ' && @board32 != ' ' && @board33 != ' '
@winner = ''
goto game_over

Console.WriteLine 'Current player: ' @playerToken
Console.Write 'Choose a column [1-3]: '
-- Console.ReadLine playerColumn
Console.ReadKeyChar playerColumn false
if @playerColumn != '1' && @playerColumn != '2' && @playerColumn != '3'
@errorMessage = 'You must enter a value of 1, 2, or 3.'
goto game_loop

Console.WriteLine ''
Console.Write 'Choose a row [1-3]: '
-- Console.ReadLine playerRow
Console.ReadKeyChar playerRow false

if @playerRow != '1' && @playerRow != '2' && @playerRow != '3'
@errorMessage = 'You must enter a value of 1, 2, or 3.'
goto game_loop

// Set player node
if @playerColumn == '1' && @playerRow == '1'
@board11 = @playerToken
elseif @playerColumn == '2' && @playerRow == '1'
@board21 = @playerToken
elseif @playerColumn == '3' && @playerRow == '1'
@board31 = @playerToken
elseif @playerColumn == '1' && @playerRow == '2'
@board12 = @playerToken
elseif @playerColumn == '2' && @playerRow == '2'
@board22 = @playerToken
elseif @playerColumn == '3' && @playerRow == '2'
@board32 = @playerToken
elseif @playerColumn == '1' && @playerRow == '3'
@board13 = @playerToken
elseif @playerColumn == '2' && @playerRow == '3'
@board23 = @playerToken
elseif @playerColumn == '3' && @playerRow == '3'
@board33 = @playerToken

// Change player
if @playerToken == x
@playerToken = o
else
@playerToken = x

@errorMessage = ''
goto game_loop

game_over:
if @winner == ''
Console.WriteLine 'The game is a tie!'
else
Console.WriteLine @winner ' has won the game!'

Console.Write 'Play again? [Y/N]: '
Console.ReadKeyChar playAgainChoice true
Console.WriteLine ''
if @playAgainChoice == 'y' || @playAgainChoice == 'Y'
goto clear_board
Now I'm off to implement a few more packages (arrays for one lol) and do a little optimization. I've attached the little bit of documentation I've written up in case anyone is interested.

[edit]
For the curious, here is the C# code to run the above:
 
using Scribe;
 
namespace TicTacToe
{
	class Program
	{
		static void Main(string[] args)
		{
			var virtualMachine = new VirtualMachine();
			Scribe.Packages.Console.Register(virtualMachine);
			var thread = virtualMachine.LoadFile(@"C:\Users\Public\tictactoe.scribe");
			thread.Start(virtualMachine);
			while(thread.IsRunning);
		}
	}
}
I also updated the game's code above so that it allows you to replay without the console closing.

[edit]
Apparently at some point I switched from loop to while. Makes sense seeing as how that is what is used in most languages, but I don't quite remember doing so. I'll have to update the document to reflect this.

[edit]
Here is another example game, Guess the Number. This one includes use of the new Array package:
 
// -------------------------------------------------------------------------
// An implementation of Guess the Number written on the Scribe scripting
// library.
// Written by Donny Beals - February 28th, 2013
// Copyright © Beals Software 2013
// -------------------------------------------------------------------------
 
initialize:
Array.Create numbersGuessed 10 true
@choiceMessage = ''
Random.NextInRange numberToGuess 1, 10
 
game_loop:
Console.Clear
 
@index = 0
Array.Count numberOfGuesses @numbersGuessed
 
Console.Write 'Numbers guessed: '
while @index < @numberOfGuesses
	Array.GetValue arrayValue @numbersGuessed @index
	Console.Write @arrayValue ' '
	@index += 1
Console.WriteLine ''
	
Console.WriteLine @choiceMessage
Console.Write 'Choose a number from 1 to 9: '
Console.ReadKeyChar playerChoice false
 
if @playerChoice != '1' && @playerChoice != '2' && @playerChoice != '3' && @playerChoice != '4' && @playerChoice != '5' && @playerChoice != '6' && @playerChoice != '7' && @playerChoice != '8' && @playerChoice != '9'
	@choiceMessage = 'You must enter a valid number from 1 to 9.'
	goto game_loop
 
if @playerChoice < @numberToGuess
	@choiceMessage = 'Your guess is too low.'
	Array.AddValue @numbersGuessed @playerChoice
elseif @playerChoice > @numberToGuess
	@choiceMessage = 'Your guess is too high.'
	Array.AddValue @numbersGuessed @playerChoice
else
	goto game_over
	
goto game_loop
 
game_over:
Console.WriteLine ''
Console.WriteLine 'You guessed the number (' @numberToGuess ')'
 
Console.Write 'Play again? [Y/N]: '
Console.ReadKeyChar playAgainChoice true
Console.WriteLine ''
if @playAgainChoice == 'y' || @playAgainChoice == 'Y'
	goto initialize

Attached Files









PARTNERS