From 6ca2609237e979b84d84578d099fc11000b15958 Mon Sep 17 00:00:00 2001 From: Jeremy Rand Date: Wed, 15 Jul 2015 18:27:40 -0500 Subject: [PATCH] Create the project. Write some code to manage a set of puzzles. Write some code to manage a sudoku game. Start work on the UI for the game. --- a2sudoku.xcodeproj/project.pbxproj | 15 + .../xcschemes/a2sudoku.xcscheme | 34 + a2sudoku/Makefile | 4 +- a2sudoku/a2e.hi.s | 2096 +++++++++++++++++ a2sudoku/game.c | 223 ++ a2sudoku/game.h | 39 + a2sudoku/main.c | 10 +- a2sudoku/make/V2Make.scpt | Bin 4742 -> 4714 bytes a2sudoku/puzzles.c | 125 + a2sudoku/puzzles.h | 51 + a2sudoku/ui.c | 270 +++ a2sudoku/ui.h | 23 + 12 files changed, 2886 insertions(+), 4 deletions(-) create mode 100644 a2sudoku/a2e.hi.s create mode 100644 a2sudoku/game.c create mode 100644 a2sudoku/game.h create mode 100644 a2sudoku/puzzles.c create mode 100644 a2sudoku/puzzles.h create mode 100644 a2sudoku/ui.c create mode 100644 a2sudoku/ui.h diff --git a/a2sudoku.xcodeproj/project.pbxproj b/a2sudoku.xcodeproj/project.pbxproj index 906c2dd..0e12c53 100644 --- a/a2sudoku.xcodeproj/project.pbxproj +++ b/a2sudoku.xcodeproj/project.pbxproj @@ -17,6 +17,13 @@ 9DEE9C2E1B569637003E353E /* prodos_template.dsk */ = {isa = PBXFileReference; lastKnownFileType = file; name = prodos_template.dsk; path = make/prodos_template.dsk; sourceTree = ""; }; 9DEE9C2F1B569637003E353E /* tail.mk */ = {isa = PBXFileReference; lastKnownFileType = text; name = tail.mk; path = make/tail.mk; sourceTree = ""; }; 9DEE9C301B569638003E353E /* V2Make.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; name = V2Make.scpt; path = make/V2Make.scpt; sourceTree = ""; }; + 9DEE9C361B569717003E353E /* puzzles.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = puzzles.c; sourceTree = ""; }; + 9DEE9C371B569717003E353E /* puzzles.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = puzzles.h; sourceTree = ""; }; + 9DEE9C381B56979C003E353E /* game.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = game.c; sourceTree = ""; }; + 9DEE9C391B56979C003E353E /* game.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = game.h; sourceTree = ""; }; + 9DEE9C3A1B56CFC0003E353E /* ui.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ui.c; sourceTree = ""; }; + 9DEE9C3B1B56CFC0003E353E /* ui.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ui.h; sourceTree = ""; }; + 9DEE9C3C1B570AED003E353E /* a2e.hi.s */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm; path = a2e.hi.s; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXGroup section */ @@ -31,6 +38,13 @@ isa = PBXGroup; children = ( 9DEE9C261B569637003E353E /* main.c */, + 9DEE9C361B569717003E353E /* puzzles.c */, + 9DEE9C371B569717003E353E /* puzzles.h */, + 9DEE9C381B56979C003E353E /* game.c */, + 9DEE9C391B56979C003E353E /* game.h */, + 9DEE9C3A1B56CFC0003E353E /* ui.c */, + 9DEE9C3B1B56CFC0003E353E /* ui.h */, + 9DEE9C3C1B570AED003E353E /* a2e.hi.s */, 9DEE9C271B569637003E353E /* Makefile */, 9DEE9C281B569637003E353E /* make */, ); @@ -216,6 +230,7 @@ 9DEE9C351B569638003E353E /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/a2sudoku.xcodeproj/xcuserdata/jrand.xcuserdatad/xcschemes/a2sudoku.xcscheme b/a2sudoku.xcodeproj/xcuserdata/jrand.xcuserdatad/xcschemes/a2sudoku.xcscheme index ba68a8e..8b4ac05 100644 --- a/a2sudoku.xcodeproj/xcuserdata/jrand.xcuserdatad/xcschemes/a2sudoku.xcscheme +++ b/a2sudoku.xcodeproj/xcuserdata/jrand.xcuserdatad/xcschemes/a2sudoku.xcscheme @@ -5,6 +5,22 @@ + + + + + + + + + + @@ -32,6 +57,15 @@ useCustomWorkingDirectory = "NO" buildConfiguration = "Release" debugDocumentVersioning = "YES"> + + + + diff --git a/a2sudoku/Makefile b/a2sudoku/Makefile index e6645c9..0491300 100644 --- a/a2sudoku/Makefile +++ b/a2sudoku/Makefile @@ -31,12 +31,12 @@ PGM=a2sudoku # MACHINE = apple2enh # MACHINE = apple2enh-dos33 # MACHINE = apple2enh-system -# MACHINE = apple2enh-loader +MACHINE = apple2enh-loader # MACHINE = apple2enh-reboot # Uncomment and set this to your starting address in Apple II memory # if necessary: -# START_ADDR = 6000 +START_ADDR = 4000 # Set the default CPU to assemble for. You can change this in the # body of a .s file using control commands like ".PC02". Uncomment diff --git a/a2sudoku/a2e.hi.s b/a2sudoku/a2e.hi.s new file mode 100644 index 0000000..f844ee3 --- /dev/null +++ b/a2sudoku/a2e.hi.s @@ -0,0 +1,2096 @@ +; +; File generated by co65 v 2.13.3 using model `cc65-module' +; +.fopt compiler,"co65 v 2.13.3" +.case on +.debuginfo off +.export _a2e_hi + +; +; CODE SEGMENT +; +.segment "CODE" +_a2e_hi: + .byte $74 + .byte $67 + .byte $69 + .byte $02 + .byte $18 + .byte $01 + .byte $C0 + .byte $00 + .byte $08 + .byte $02 + .byte $08 + .byte $08 + .byte $00 + .byte $00 + .byte $00 + .byte $00 + .word _a2e_hi+81 + .word _a2e_hi+81 + .word _a2e_hi+58 + .word _a2e_hi+82 + .word _a2e_hi+100 + .word _a2e_hi+146 + .word _a2e_hi+109 + .word _a2e_hi+119 + .word _a2e_hi+124 + .word _a2e_hi+135 + .word _a2e_hi+146 + .word _a2e_hi+152 + .word _a2e_hi+152 + .word _a2e_hi+157 + .word _a2e_hi+224 + .word _a2e_hi+255 + .word _a2e_hi+280 + .word _a2e_hi+302 + .word _a2e_hi+659 + .word _a2e_hi+668 + .byte $00 + .byte $00 + .byte $AD + .byte $18 + .byte $C0 + .byte $8D + .word BSS+1 + .byte $8D + .byte $00 + .byte $C0 + .byte $2C + .byte $57 + .byte $C0 + .byte $2C + .byte $52 + .byte $C0 + .byte $2C + .byte $50 + .byte $C0 + .byte $A9 + .byte $00 + .byte $8D + .word BSS+0 + .byte $60 + .byte $2C + .byte $51 + .byte $C0 + .byte $2C + .byte $54 + .byte $C0 + .byte $AD + .word BSS+1 + .byte $10 + .byte $03 + .byte $8D + .byte $01 + .byte $C0 + .byte $2C + .byte $56 + .byte $C0 + .byte $60 + .byte $AD + .word BSS+0 + .byte $A2 + .byte $00 + .byte $8E + .word BSS+0 + .byte $60 + .byte $2C + .byte $82 + .byte $C0 + .byte $20 + .byte $F2 + .byte $F3 + .byte $2C + .byte $80 + .byte $C0 + .byte $60 + .byte $AA + .byte $BD + .byte $54 + .byte $C0 + .byte $60 + .byte $AA + .byte $F0 + .byte $03 + .byte $A9 + .byte $40 + .byte $2C + .byte $A9 + .byte $20 + .byte $85 + .byte $E6 + .byte $60 + .byte $2C + .byte $82 + .byte $C0 + .byte $AA + .byte $20 + .byte $EC + .byte $F6 + .byte $2C + .byte $80 + .byte $C0 + .byte $60 + .byte $A9 + .byte $06 + .byte $8D + .word BSS+0 + .byte $60 + .byte $A9 + .byte <(_a2e_hi+34) + .byte $A2 + .byte >(_a2e_hi+802) + .byte $60 + .byte $2C + .byte $82 + .byte $C0 + .byte $A6 + .byte <(ZEROPAGE+8) + .byte $A4 + .byte <(ZEROPAGE+9) + .byte $A5 + .byte <(ZEROPAGE+10) + .byte $20 + .byte $57 + .byte $F4 + .byte $2C + .byte $80 + .byte $C0 + .byte $60 + .byte $A5 + .byte <(ZEROPAGE+11) + .byte $30 + .byte $2E + .byte $A5 + .byte <(ZEROPAGE+9) + .byte $30 + .byte $2A + .byte $A5 + .byte <(ZEROPAGE+8) + .byte $A6 + .byte <(ZEROPAGE+9) + .byte $85 + .byte <(ZEROPAGE+16) + .byte $86 + .byte <(ZEROPAGE+17) + .byte $A2 + .byte <(ZEROPAGE+16) + .byte $AD + .word _a2e_hi+4 + .byte $AC + .word _a2e_hi+5 + .byte $20 + .word _a2e_hi+768 + .byte $B0 + .byte $15 + .byte $A5 + .byte <(ZEROPAGE+10) + .byte $A6 + .byte <(ZEROPAGE+11) + .byte $85 + .byte <(ZEROPAGE+16) + .byte $86 + .byte <(ZEROPAGE+17) + .byte $A2 + .byte <(ZEROPAGE+16) + .byte $AD + .word _a2e_hi+6 + .byte $AC + .word _a2e_hi+7 + .byte $20 + .word _a2e_hi+768 + .byte $90 + .byte $BE + .byte $60 + .byte $2C + .byte $82 + .byte $C0 + .byte $A6 + .byte <(ZEROPAGE+8) + .byte $A4 + .byte <(ZEROPAGE+9) + .byte $A5 + .byte <(ZEROPAGE+10) + .byte $20 + .byte $11 + .byte $F4 + .byte $B1 + .byte $26 + .byte $25 + .byte $30 + .byte $0A + .byte $F0 + .byte $02 + .byte $A9 + .byte $03 + .byte $90 + .byte $02 + .byte $69 + .byte $03 + .byte $A2 + .byte $00 + .byte $2C + .byte $80 + .byte $C0 + .byte $60 + .byte $2C + .byte $82 + .byte $C0 + .byte $A6 + .byte <(ZEROPAGE+8) + .byte $A4 + .byte <(ZEROPAGE+9) + .byte $A5 + .byte <(ZEROPAGE+10) + .byte $20 + .byte $11 + .byte $F4 + .byte $A5 + .byte <(ZEROPAGE+12) + .byte $A6 + .byte <(ZEROPAGE+13) + .byte $A4 + .byte <(ZEROPAGE+14) + .byte $20 + .byte $3A + .byte $F5 + .byte $2C + .byte $80 + .byte $C0 + .byte $60 + .byte $E6 + .byte <(ZEROPAGE+14) + .byte $A5 + .byte <(ZEROPAGE+14) + .byte $48 + .byte $A5 + .byte <(ZEROPAGE+10) + .byte $85 + .byte <(ZEROPAGE+14) + .byte $20 + .word _a2e_hi+255 + .byte $68 + .byte $85 + .byte <(ZEROPAGE+14) + .byte $E6 + .byte <(ZEROPAGE+10) + .byte $C5 + .byte <(ZEROPAGE+10) + .byte $D0 + .byte $ED + .byte $60 + .byte $A5 + .byte <(ZEROPAGE+16) + .byte $D0 + .byte $03 + .byte $4C + .word _a2e_hi+173 + .byte $85 + .byte <(ZEROPAGE+12) + .byte $A9 + .byte $00 + .byte $85 + .byte <(ZEROPAGE+13) + .byte $85 + .byte <(ZEROPAGE+14) + .byte $85 + .byte <(ZEROPAGE+15) + .byte $85 + .byte <(ZEROPAGE+2) + .byte $85 + .byte <(ZEROPAGE+3) + .byte $A5 + .byte <(ZEROPAGE+8) + .byte $A6 + .byte <(ZEROPAGE+9) + .byte $85 + .byte <(ZEROPAGE+4) + .byte $86 + .byte <(ZEROPAGE+5) + .byte $A5 + .byte <(ZEROPAGE+10) + .byte $A6 + .byte <(ZEROPAGE+11) + .byte $85 + .byte <(ZEROPAGE+6) + .byte $86 + .byte <(ZEROPAGE+7) + .byte $A2 + .byte <(ZEROPAGE+14) + .byte $A5 + .byte <(ZEROPAGE+12) + .byte $A4 + .byte <(ZEROPAGE+13) + .byte $20 + .word _a2e_hi+768 + .byte $90 + .byte $01 + .byte $60 + .byte $A5 + .byte <(ZEROPAGE+4) + .byte $18 + .byte $65 + .byte <(ZEROPAGE+12) + .byte $85 + .byte <(ZEROPAGE+8) + .byte $A5 + .byte <(ZEROPAGE+5) + .byte $65 + .byte <(ZEROPAGE+13) + .byte $85 + .byte <(ZEROPAGE+9) + .byte $A5 + .byte <(ZEROPAGE+6) + .byte $18 + .byte $65 + .byte <(ZEROPAGE+14) + .byte $85 + .byte <(ZEROPAGE+10) + .byte $48 + .byte $A5 + .byte <(ZEROPAGE+7) + .byte $65 + .byte <(ZEROPAGE+15) + .byte $85 + .byte <(ZEROPAGE+11) + .byte $48 + .byte $20 + .word _a2e_hi+173 + .byte $A5 + .byte <(ZEROPAGE+6) + .byte $38 + .byte $E5 + .byte <(ZEROPAGE+14) + .byte $85 + .byte <(ZEROPAGE+10) + .byte $8D + .word BSS+6 + .byte $A5 + .byte <(ZEROPAGE+7) + .byte $E5 + .byte <(ZEROPAGE+15) + .byte $85 + .byte <(ZEROPAGE+11) + .byte $8D + .word BSS+7 + .byte $20 + .word _a2e_hi+173 + .byte $68 + .byte $85 + .byte <(ZEROPAGE+11) + .byte $68 + .byte $85 + .byte <(ZEROPAGE+10) + .byte $A5 + .byte <(ZEROPAGE+4) + .byte $38 + .byte $E5 + .byte <(ZEROPAGE+12) + .byte $85 + .byte <(ZEROPAGE+8) + .byte $A5 + .byte <(ZEROPAGE+5) + .byte $E5 + .byte <(ZEROPAGE+13) + .byte $85 + .byte <(ZEROPAGE+9) + .byte $20 + .word _a2e_hi+173 + .byte $AD + .word BSS+6 + .byte $85 + .byte <(ZEROPAGE+10) + .byte $AD + .word BSS+7 + .byte $85 + .byte <(ZEROPAGE+11) + .byte $20 + .word _a2e_hi+173 + .byte $A5 + .byte <(ZEROPAGE+4) + .byte $18 + .byte $65 + .byte <(ZEROPAGE+14) + .byte $85 + .byte <(ZEROPAGE+8) + .byte $A5 + .byte <(ZEROPAGE+5) + .byte $65 + .byte <(ZEROPAGE+15) + .byte $85 + .byte <(ZEROPAGE+9) + .byte $A5 + .byte <(ZEROPAGE+6) + .byte $18 + .byte $65 + .byte <(ZEROPAGE+12) + .byte $85 + .byte <(ZEROPAGE+10) + .byte $48 + .byte $A5 + .byte <(ZEROPAGE+7) + .byte $65 + .byte <(ZEROPAGE+13) + .byte $85 + .byte <(ZEROPAGE+11) + .byte $48 + .byte $20 + .word _a2e_hi+173 + .byte $A5 + .byte <(ZEROPAGE+6) + .byte $38 + .byte $E5 + .byte <(ZEROPAGE+12) + .byte $85 + .byte <(ZEROPAGE+10) + .byte $8D + .word BSS+6 + .byte $A5 + .byte <(ZEROPAGE+7) + .byte $E5 + .byte <(ZEROPAGE+13) + .byte $85 + .byte <(ZEROPAGE+11) + .byte $8D + .word BSS+7 + .byte $20 + .word _a2e_hi+173 + .byte $68 + .byte $85 + .byte <(ZEROPAGE+11) + .byte $68 + .byte $85 + .byte <(ZEROPAGE+10) + .byte $A5 + .byte <(ZEROPAGE+4) + .byte $38 + .byte $E5 + .byte <(ZEROPAGE+14) + .byte $85 + .byte <(ZEROPAGE+8) + .byte $A5 + .byte <(ZEROPAGE+5) + .byte $E5 + .byte <(ZEROPAGE+15) + .byte $85 + .byte <(ZEROPAGE+9) + .byte $20 + .word _a2e_hi+173 + .byte $AD + .word BSS+6 + .byte $85 + .byte <(ZEROPAGE+10) + .byte $AD + .word BSS+7 + .byte $85 + .byte <(ZEROPAGE+11) + .byte $20 + .word _a2e_hi+173 + .byte $A5 + .byte <(ZEROPAGE+2) + .byte $A6 + .byte <(ZEROPAGE+3) + .byte $18 + .byte $65 + .byte <(ZEROPAGE+14) + .byte $A8 + .byte $8A + .byte $65 + .byte <(ZEROPAGE+15) + .byte $AA + .byte $98 + .byte $18 + .byte $65 + .byte <(ZEROPAGE+14) + .byte $A8 + .byte $8A + .byte $65 + .byte <(ZEROPAGE+15) + .byte $AA + .byte $98 + .byte $18 + .byte $69 + .byte $01 + .byte $90 + .byte $01 + .byte $E8 + .byte $8D + .word BSS+2 + .byte $8E + .word BSS+3 + .byte $38 + .byte $E5 + .byte <(ZEROPAGE+12) + .byte $A8 + .byte $8A + .byte $E5 + .byte <(ZEROPAGE+13) + .byte $AA + .byte $98 + .byte $38 + .byte $E5 + .byte <(ZEROPAGE+12) + .byte $A8 + .byte $8A + .byte $E5 + .byte <(ZEROPAGE+13) + .byte $AA + .byte $98 + .byte $18 + .byte $69 + .byte $01 + .byte $90 + .byte $01 + .byte $E8 + .byte $8D + .word BSS+4 + .byte $8E + .word BSS+5 + .byte $E6 + .byte <(ZEROPAGE+14) + .byte $D0 + .byte $02 + .byte $E6 + .byte <(ZEROPAGE+15) + .byte $AD + .word BSS+4 + .byte $AC + .word BSS+5 + .byte $20 + .word _a2e_hi+750 + .byte $85 + .byte <(ZEROPAGE+2) + .byte $84 + .byte <(ZEROPAGE+3) + .byte $AD + .word BSS+2 + .byte $AC + .word BSS+3 + .byte $20 + .word _a2e_hi+750 + .byte $A2 + .byte <(ZEROPAGE+2) + .byte $20 + .word _a2e_hi+768 + .byte $10 + .byte $14 + .byte $A5 + .byte <(ZEROPAGE+12) + .byte $38 + .byte $E9 + .byte $01 + .byte $85 + .byte <(ZEROPAGE+12) + .byte $B0 + .byte $02 + .byte $C6 + .byte <(ZEROPAGE+13) + .byte $AD + .word BSS+4 + .byte $AE + .word BSS+5 + .byte $4C + .word _a2e_hi+652 + .byte $AD + .word BSS+2 + .byte $AE + .word BSS+3 + .byte $85 + .byte <(ZEROPAGE+2) + .byte $86 + .byte <(ZEROPAGE+3) + .byte $4C + .word _a2e_hi+339 + .byte $86 + .byte $E7 + .byte $0A + .byte $0A + .byte $0A + .byte $0A + .byte $85 + .byte $F9 + .byte $60 + .byte $2C + .byte $82 + .byte $C0 + .byte $A6 + .byte <(ZEROPAGE+8) + .byte $A4 + .byte <(ZEROPAGE+9) + .byte $A5 + .byte <(ZEROPAGE+10) + .byte $20 + .byte $11 + .byte $F4 + .byte $AD + .word _a2e_hi+1008 + .byte $18 + .byte $69 + .byte <(_a2e_hi+42) + .byte $85 + .byte <(ZEROPAGE+18) + .byte $AD + .word _a2e_hi+1009 + .byte $69 + .byte >(_a2e_hi+810) + .byte $85 + .byte <(ZEROPAGE+19) + .byte $A0 + .byte $00 + .byte $B1 + .byte <(ZEROPAGE+12) + .byte $F0 + .byte $2D + .byte $38 + .byte $E9 + .byte $1F + .byte $0A + .byte $AA + .byte $BD + .word _a2e_hi+810 + .byte $18 + .byte $69 + .byte <(_a2e_hi+42) + .byte $85 + .byte <(ZEROPAGE+16) + .byte $BD + .word _a2e_hi+811 + .byte $69 + .byte >(_a2e_hi+810) + .byte $85 + .byte <(ZEROPAGE+17) + .byte $98 + .byte $48 + .byte $A6 + .byte <(ZEROPAGE+16) + .byte $A4 + .byte <(ZEROPAGE+17) + .byte $A5 + .byte $F9 + .byte $20 + .byte $01 + .byte $F6 + .byte $A6 + .byte <(ZEROPAGE+18) + .byte $A4 + .byte <(ZEROPAGE+19) + .byte $A5 + .byte $F9 + .byte $20 + .byte $01 + .byte $F6 + .byte $68 + .byte $A8 + .byte $C8 + .byte $D0 + .byte $CF + .byte $2C + .byte $80 + .byte $C0 + .byte $60 + .byte $C0 + .byte $00 + .byte $10 + .byte $0D + .byte $18 + .byte $49 + .byte $FF + .byte $69 + .byte $01 + .byte $48 + .byte $98 + .byte $49 + .byte $FF + .byte $69 + .byte $00 + .byte $A8 + .byte $68 + .byte $60 + .byte $85 + .byte <(ZEROPAGE+18) + .byte $84 + .byte <(ZEROPAGE+19) + .byte $B5 + .byte $00 + .byte $48 + .byte $B5 + .byte $01 + .byte $A8 + .byte $68 + .byte $AA + .byte $98 + .byte $38 + .byte $E5 + .byte <(ZEROPAGE+19) + .byte $D0 + .byte $09 + .byte $E4 + .byte <(ZEROPAGE+18) + .byte $F0 + .byte $04 + .byte $69 + .byte $FF + .byte $09 + .byte $01 + .byte $60 + .byte $50 + .byte $04 + .byte $49 + .byte $FF + .byte $09 + .byte $01 + .byte $60 + .byte $00 + .byte $01 + .byte $02 + .byte $03 + .byte $04 + .byte $05 + .byte $06 + .byte $07 + .byte $64 + .byte $01 + .byte $D0 + .byte $00 + .byte $D5 + .byte $00 + .byte $DA + .byte $00 + .byte $E0 + .byte $00 + .byte $EF + .byte $00 + .byte $FE + .byte $00 + .byte $0C + .byte $01 + .byte $19 + .byte $01 + .byte $1D + .byte $01 + .byte $25 + .byte $01 + .byte $2D + .byte $01 + .byte $3D + .byte $01 + .byte $46 + .byte $01 + .byte $4B + .byte $01 + .byte $52 + .byte $01 + .byte $56 + .byte $01 + .byte $60 + .byte $01 + .byte $70 + .byte $01 + .byte $77 + .byte $01 + .byte $83 + .byte $01 + .byte $8E + .byte $01 + .byte $9A + .byte $01 + .byte $A7 + .byte $01 + .byte $B6 + .byte $01 + .byte $BF + .byte $01 + .byte $CE + .byte $01 + .byte $DD + .byte $01 + .byte $E2 + .byte $01 + .byte $E7 + .byte $01 + .byte $F9 + .byte $01 + .byte $03 + .byte $02 + .byte $15 + .byte $02 + .byte $1F + .byte $02 + .byte $32 + .byte $02 + .byte $42 + .byte $02 + .byte $52 + .byte $02 + .byte $5E + .byte $02 + .byte $6C + .byte $02 + .byte $79 + .byte $02 + .byte $85 + .byte $02 + .byte $91 + .byte $02 + .byte $A1 + .byte $02 + .byte $A9 + .byte $02 + .byte $B2 + .byte $02 + .byte $BF + .byte $02 + .byte $C5 + .byte $02 + .byte $D5 + .byte $02 + .byte $E5 + .byte $02 + .byte $F4 + .byte $02 + .byte $00 + .byte $03 + .byte $10 + .byte $03 + .byte $1F + .byte $03 + .byte $2D + .byte $03 + .byte $35 + .byte $03 + .byte $44 + .byte $03 + .byte $53 + .byte $03 + .byte $63 + .byte $03 + .byte $71 + .byte $03 + .byte $7B + .byte $03 + .byte $85 + .byte $03 + .byte $91 + .byte $03 + .byte $97 + .byte $03 + .byte $A3 + .byte $03 + .byte $B6 + .byte $03 + .byte $BF + .byte $03 + .byte $C3 + .byte $03 + .byte $CF + .byte $03 + .byte $DC + .byte $03 + .byte $E4 + .byte $03 + .byte $F3 + .byte $03 + .byte $00 + .byte $04 + .byte $0A + .byte $04 + .byte $19 + .byte $04 + .byte $25 + .byte $04 + .byte $2A + .byte $04 + .byte $32 + .byte $04 + .byte $3C + .byte $04 + .byte $43 + .byte $04 + .byte $50 + .byte $04 + .byte $5A + .byte $04 + .byte $66 + .byte $04 + .byte $72 + .byte $04 + .byte $7E + .byte $04 + .byte $87 + .byte $04 + .byte $94 + .byte $04 + .byte $9C + .byte $04 + .byte $A8 + .byte $04 + .byte $B4 + .byte $04 + .byte $C1 + .byte $04 + .byte $CC + .byte $04 + .byte $DB + .byte $04 + .byte $E6 + .byte $04 + .byte $EE + .byte $04 + .byte $F3 + .byte $04 + .byte $FB + .byte $04 + .byte $04 + .byte $05 + .byte $1A + .byte $05 + .byte $1F + .byte $05 + .byte $24 + .byte $05 + .byte $29 + .byte $05 + .byte $22 + .byte $01 + .byte $00 + .byte $00 + .byte $00 + .byte $00 + .byte $09 + .byte $89 + .byte $92 + .byte $92 + .byte $00 + .byte $36 + .byte $36 + .byte $16 + .byte $0E + .byte $00 + .byte $0D + .byte $FE + .byte $6E + .byte $96 + .byte $52 + .byte $00 + .byte $69 + .byte $FE + .byte $17 + .byte $2D + .byte $2D + .byte $1E + .byte $1F + .byte $17 + .byte $2D + .byte $2D + .byte $1E + .byte $1F + .byte $6E + .byte $4E + .byte $00 + .byte $09 + .byte $8D + .byte $3F + .byte $BF + .byte $0D + .byte $15 + .byte $3F + .byte $0E + .byte $0D + .byte $1E + .byte $3F + .byte $77 + .byte $71 + .byte $09 + .byte $00 + .byte $6D + .byte $11 + .byte $DF + .byte $77 + .byte $09 + .byte $1E + .byte $17 + .byte $4D + .byte $3A + .byte $DF + .byte $4E + .byte $29 + .byte $0E + .byte $00 + .byte $A9 + .byte $1F + .byte $6E + .byte $1E + .byte $17 + .byte $0D + .byte $0D + .byte $1E + .byte $DF + .byte $0E + .byte $6D + .byte $0E + .byte $00 + .byte $36 + .byte $96 + .byte $52 + .byte $00 + .byte $09 + .byte $1E + .byte $17 + .byte $36 + .byte $15 + .byte $0E + .byte $0E + .byte $00 + .byte $15 + .byte $0E + .byte $36 + .byte $1E + .byte $17 + .byte $4E + .byte $01 + .byte $00 + .byte $09 + .byte $8D + .byte $1F + .byte $1F + .byte $0E + .byte $2D + .byte $1E + .byte $17 + .byte $2D + .byte $15 + .byte $1F + .byte $1F + .byte $4E + .byte $4E + .byte $01 + .byte $00 + .byte $89 + .byte $6E + .byte $3A + .byte $3F + .byte $77 + .byte $31 + .byte $56 + .byte $09 + .byte $00 + .byte $92 + .byte $8A + .byte $F6 + .byte $0D + .byte $00 + .byte $52 + .byte $89 + .byte $3F + .byte $B7 + .byte $52 + .byte $49 + .byte $00 + .byte $92 + .byte $92 + .byte $0E + .byte $00 + .byte $49 + .byte $11 + .byte $17 + .byte $1E + .byte $17 + .byte $1E + .byte $56 + .byte $49 + .byte $01 + .byte $00 + .byte $29 + .byte $AD + .byte $DF + .byte $33 + .byte $4D + .byte $35 + .byte $1F + .byte $1F + .byte $2E + .byte $4D + .byte $FE + .byte $1B + .byte $0E + .byte $2D + .byte $4E + .byte $00 + .byte $31 + .byte $77 + .byte $36 + .byte $BE + .byte $2D + .byte $0E + .byte $00 + .byte $29 + .byte $AD + .byte $DF + .byte $73 + .byte $49 + .byte $1E + .byte $BF + .byte $1E + .byte $2E + .byte $2D + .byte $75 + .byte $00 + .byte $2D + .byte $2D + .byte $BE + .byte $3E + .byte $4E + .byte $FE + .byte $1B + .byte $0E + .byte $2D + .byte $4E + .byte $00 + .byte $49 + .byte $3E + .byte $17 + .byte $0D + .byte $FE + .byte $33 + .byte $2D + .byte $2D + .byte $1E + .byte $76 + .byte $01 + .byte $00 + .byte $2D + .byte $2D + .byte $DE + .byte $1B + .byte $2E + .byte $2D + .byte $15 + .byte $36 + .byte $DF + .byte $73 + .byte $2D + .byte $4E + .byte $00 + .byte $09 + .byte $2D + .byte $DE + .byte $BB + .byte $4D + .byte $3A + .byte $3F + .byte $6E + .byte $09 + .byte $FE + .byte $1B + .byte $0E + .byte $2D + .byte $4E + .byte $00 + .byte $2D + .byte $2D + .byte $BE + .byte $1E + .byte $17 + .byte $36 + .byte $4E + .byte $09 + .byte $00 + .byte $29 + .byte $AD + .byte $DF + .byte $33 + .byte $4D + .byte $F1 + .byte $3F + .byte $17 + .byte $4D + .byte $31 + .byte $DF + .byte $73 + .byte $2D + .byte $4E + .byte $00 + .byte $29 + .byte $AD + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $3F + .byte $77 + .byte $09 + .byte $1E + .byte $DF + .byte $2A + .byte $75 + .byte $09 + .byte $00 + .byte $12 + .byte $16 + .byte $96 + .byte $01 + .byte $00 + .byte $52 + .byte $B2 + .byte $F6 + .byte $0D + .byte $00 + .byte $49 + .byte $3E + .byte $17 + .byte $2D + .byte $2D + .byte $35 + .byte $3F + .byte $3F + .byte $3F + .byte $0E + .byte $2D + .byte $2D + .byte $F5 + .byte $1B + .byte $77 + .byte $4E + .byte $09 + .byte $00 + .byte $12 + .byte $2D + .byte $2D + .byte $DE + .byte $9B + .byte $2D + .byte $2D + .byte $96 + .byte $01 + .byte $00 + .byte $49 + .byte $15 + .byte $FF + .byte $13 + .byte $2D + .byte $2D + .byte $AD + .byte $3F + .byte $3F + .byte $3F + .byte $2E + .byte $2D + .byte $2D + .byte $1E + .byte $37 + .byte $4E + .byte $09 + .byte $00 + .byte $29 + .byte $AD + .byte $DF + .byte $73 + .byte $09 + .byte $1E + .byte $B6 + .byte $4E + .byte $01 + .byte $00 + .byte $09 + .byte $2D + .byte $3E + .byte $37 + .byte $2D + .byte $3E + .byte $FF + .byte $2A + .byte $2D + .byte $2D + .byte $F5 + .byte $3F + .byte $3F + .byte $0E + .byte $2D + .byte $1E + .byte $4D + .byte $01 + .byte $00 + .byte $09 + .byte $15 + .byte $1F + .byte $17 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $2D + .byte $2D + .byte $FE + .byte $1B + .byte $6E + .byte $09 + .byte $0E + .byte $00 + .byte $2D + .byte $AD + .byte $DF + .byte $33 + .byte $4D + .byte $F1 + .byte $3F + .byte $37 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $2D + .byte $75 + .byte $01 + .byte $00 + .byte $29 + .byte $AD + .byte $DF + .byte $33 + .byte $36 + .byte $4D + .byte $11 + .byte $DF + .byte $73 + .byte $2D + .byte $4E + .byte $00 + .byte $2D + .byte $AD + .byte $DF + .byte $6E + .byte $31 + .byte $DF + .byte $6E + .byte $31 + .byte $DF + .byte $17 + .byte $2D + .byte $75 + .byte $01 + .byte $00 + .byte $2D + .byte $2D + .byte $DE + .byte $1B + .byte $6E + .byte $11 + .byte $3F + .byte $37 + .byte $36 + .byte $2D + .byte $2D + .byte $0E + .byte $00 + .byte $2D + .byte $2D + .byte $DE + .byte $1B + .byte $6E + .byte $11 + .byte $3F + .byte $37 + .byte $36 + .byte $4E + .byte $49 + .byte $00 + .byte $29 + .byte $AD + .byte $DF + .byte $33 + .byte $36 + .byte $4D + .byte $35 + .byte $DF + .byte $73 + .byte $2D + .byte $75 + .byte $00 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $3F + .byte $3F + .byte $6E + .byte $09 + .byte $FE + .byte $1B + .byte $6E + .byte $09 + .byte $0E + .byte $00 + .byte $2D + .byte $1E + .byte $36 + .byte $36 + .byte $17 + .byte $2D + .byte $0E + .byte $00 + .byte $49 + .byte $31 + .byte $36 + .byte $36 + .byte $DF + .byte $73 + .byte $2D + .byte $4E + .byte $00 + .byte $4D + .byte $F1 + .byte $DF + .byte $6E + .byte $1E + .byte $37 + .byte $0D + .byte $15 + .byte $DF + .byte $6E + .byte $09 + .byte $0E + .byte $00 + .byte $36 + .byte $36 + .byte $36 + .byte $2D + .byte $75 + .byte $00 + .byte $4D + .byte $31 + .byte $FF + .byte $37 + .byte $0D + .byte $0D + .byte $FE + .byte $1F + .byte $6E + .byte $09 + .byte $FE + .byte $1B + .byte $6E + .byte $09 + .byte $0E + .byte $00 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $6D + .byte $31 + .byte $1F + .byte $1F + .byte $6E + .byte $29 + .byte $FE + .byte $1B + .byte $6E + .byte $09 + .byte $0E + .byte $00 + .byte $29 + .byte $AD + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $DF + .byte $73 + .byte $2D + .byte $4E + .byte $00 + .byte $2D + .byte $AD + .byte $DF + .byte $33 + .byte $4D + .byte $F1 + .byte $3F + .byte $37 + .byte $36 + .byte $4E + .byte $49 + .byte $00 + .byte $29 + .byte $AD + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $0D + .byte $0D + .byte $1E + .byte $DF + .byte $0E + .byte $6D + .byte $0E + .byte $00 + .byte $2D + .byte $AD + .byte $DF + .byte $33 + .byte $4D + .byte $F1 + .byte $3F + .byte $37 + .byte $0D + .byte $15 + .byte $DF + .byte $6E + .byte $09 + .byte $0E + .byte $00 + .byte $29 + .byte $AD + .byte $DF + .byte $33 + .byte $4D + .byte $3A + .byte $77 + .byte $09 + .byte $FE + .byte $1B + .byte $0E + .byte $2D + .byte $4E + .byte $00 + .byte $2D + .byte $2D + .byte $DE + .byte $36 + .byte $36 + .byte $76 + .byte $09 + .byte $00 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $DF + .byte $73 + .byte $2D + .byte $4E + .byte $00 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $4D + .byte $F1 + .byte $1F + .byte $0E + .byte $4E + .byte $01 + .byte $00 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $1F + .byte $1F + .byte $6E + .byte $0D + .byte $3E + .byte $1F + .byte $37 + .byte $4D + .byte $71 + .byte $00 + .byte $4D + .byte $31 + .byte $DF + .byte $73 + .byte $0D + .byte $1E + .byte $17 + .byte $0D + .byte $15 + .byte $DF + .byte $33 + .byte $4D + .byte $71 + .byte $00 + .byte $4D + .byte $31 + .byte $DF + .byte $73 + .byte $0D + .byte $1E + .byte $36 + .byte $76 + .byte $09 + .byte $00 + .byte $2D + .byte $2D + .byte $BE + .byte $1E + .byte $17 + .byte $1E + .byte $2E + .byte $2D + .byte $75 + .byte $00 + .byte $2D + .byte $2D + .byte $DE + .byte $3B + .byte $2E + .byte $3E + .byte $2E + .byte $3E + .byte $2E + .byte $2D + .byte $75 + .byte $00 + .byte $72 + .byte $15 + .byte $0E + .byte $15 + .byte $56 + .byte $00 + .byte $2D + .byte $2D + .byte $3E + .byte $2E + .byte $3E + .byte $2E + .byte $3E + .byte $DF + .byte $2A + .byte $2D + .byte $75 + .byte $00 + .byte $49 + .byte $15 + .byte $3F + .byte $17 + .byte $2D + .byte $2D + .byte $15 + .byte $3F + .byte $3F + .byte $3F + .byte $4E + .byte $2D + .byte $3E + .byte $37 + .byte $2D + .byte $3E + .byte $6F + .byte $49 + .byte $00 + .byte $92 + .byte $92 + .byte $49 + .byte $11 + .byte $3F + .byte $3F + .byte $4D + .byte $09 + .byte $00 + .byte $76 + .byte $96 + .byte $52 + .byte $00 + .byte $52 + .byte $2D + .byte $35 + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $FF + .byte $73 + .byte $6D + .byte $0E + .byte $00 + .byte $36 + .byte $2D + .byte $AD + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $2D + .byte $75 + .byte $01 + .byte $00 + .byte $52 + .byte $2D + .byte $DE + .byte $33 + .byte $76 + .byte $2D + .byte $0E + .byte $00 + .byte $49 + .byte $31 + .byte $DF + .byte $2A + .byte $2D + .byte $FE + .byte $1B + .byte $6E + .byte $09 + .byte $FE + .byte $1B + .byte $0E + .byte $2D + .byte $75 + .byte $00 + .byte $52 + .byte $2D + .byte $15 + .byte $DF + .byte $33 + .byte $2D + .byte $2D + .byte $DE + .byte $1B + .byte $0E + .byte $2D + .byte $75 + .byte $00 + .byte $09 + .byte $F5 + .byte $33 + .byte $8D + .byte $3F + .byte $77 + .byte $36 + .byte $4E + .byte $01 + .byte $00 + .byte $52 + .byte $2D + .byte $35 + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $3F + .byte $77 + .byte $09 + .byte $1E + .byte $3F + .byte $4D + .byte $01 + .byte $00 + .byte $36 + .byte $2D + .byte $AD + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $4D + .byte $71 + .byte $00 + .byte $16 + .byte $36 + .byte $36 + .byte $0E + .byte $00 + .byte $09 + .byte $9E + .byte $35 + .byte $36 + .byte $F6 + .byte $6F + .byte $01 + .byte $00 + .byte $36 + .byte $4D + .byte $1E + .byte $1F + .byte $2E + .byte $15 + .byte $1F + .byte $6E + .byte $71 + .byte $00 + .byte $35 + .byte $36 + .byte $36 + .byte $17 + .byte $2D + .byte $0E + .byte $00 + .byte $12 + .byte $2D + .byte $AD + .byte $1F + .byte $1F + .byte $6E + .byte $0D + .byte $FE + .byte $1F + .byte $6E + .byte $0D + .byte $0E + .byte $00 + .byte $12 + .byte $2D + .byte $15 + .byte $DF + .byte $6E + .byte $31 + .byte $DF + .byte $6E + .byte $71 + .byte $00 + .byte $52 + .byte $2D + .byte $15 + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $DF + .byte $73 + .byte $2D + .byte $4E + .byte $00 + .byte $12 + .byte $2D + .byte $AD + .byte $DF + .byte $33 + .byte $4D + .byte $F1 + .byte $3F + .byte $37 + .byte $6E + .byte $49 + .byte $00 + .byte $52 + .byte $2D + .byte $35 + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $3F + .byte $77 + .byte $09 + .byte $2E + .byte $00 + .byte $12 + .byte $0D + .byte $AD + .byte $DF + .byte $37 + .byte $36 + .byte $4E + .byte $49 + .byte $00 + .byte $52 + .byte $2D + .byte $F5 + .byte $DB + .byte $0E + .byte $2D + .byte $15 + .byte $DF + .byte $13 + .byte $2D + .byte $75 + .byte $01 + .byte $00 + .byte $31 + .byte $17 + .byte $2D + .byte $F5 + .byte $33 + .byte $76 + .byte $75 + .byte $00 + .byte $12 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $FF + .byte $73 + .byte $6D + .byte $0E + .byte $00 + .byte $12 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $4D + .byte $F1 + .byte $1F + .byte $0E + .byte $4E + .byte $01 + .byte $00 + .byte $12 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $0D + .byte $0D + .byte $FE + .byte $1F + .byte $0E + .byte $0D + .byte $4E + .byte $00 + .byte $12 + .byte $4D + .byte $F1 + .byte $1F + .byte $0E + .byte $15 + .byte $1F + .byte $17 + .byte $4D + .byte $71 + .byte $00 + .byte $12 + .byte $4D + .byte $31 + .byte $DF + .byte $33 + .byte $4D + .byte $31 + .byte $3F + .byte $77 + .byte $09 + .byte $1E + .byte $3F + .byte $4D + .byte $01 + .byte $00 + .byte $12 + .byte $2D + .byte $2D + .byte $1E + .byte $17 + .byte $1E + .byte $17 + .byte $2D + .byte $2D + .byte $0E + .byte $00 + .byte $09 + .byte $F5 + .byte $33 + .byte $1E + .byte $0E + .byte $76 + .byte $75 + .byte $00 + .byte $36 + .byte $36 + .byte $36 + .byte $2E + .byte $00 + .byte $AD + .byte $AE + .byte $17 + .byte $FE + .byte $2A + .byte $4E + .byte $01 + .byte $00 + .byte $69 + .byte $11 + .byte $1F + .byte $1F + .byte $4E + .byte $B1 + .byte $92 + .byte $09 + .byte $00 + .byte $2D + .byte $2D + .byte $35 + .byte $3F + .byte $3F + .byte $37 + .byte $2D + .byte $2D + .byte $35 + .byte $3F + .byte $3F + .byte $37 + .byte $2D + .byte $2D + .byte $35 + .byte $3F + .byte $3F + .byte $37 + .byte $2D + .byte $2D + .byte $75 + .byte $00 + .byte $40 + .byte $C0 + .byte $40 + .byte $18 + .byte $00 + .byte $40 + .byte $C0 + .byte $40 + .byte $43 + .byte $00 + .byte $40 + .byte $C0 + .byte $40 + .byte $08 + .byte $00 + .byte $19 + .byte $00 + .byte $00 + +; +; DATA SEGMENT +; +.segment "DATA" +DATA: + +; +; BSS SEGMENT +; +.segment "BSS" +BSS: + .res 8 + +; +; ZEROPAGE SEGMENT +; +.import __ZP_START__ ; Linker generated symbol +ZEROPAGE = __ZP_START__ + +.end diff --git a/a2sudoku/game.c b/a2sudoku/game.c new file mode 100644 index 0000000..365298a --- /dev/null +++ b/a2sudoku/game.c @@ -0,0 +1,223 @@ +// +// game.c +// a2sudoku +// +// Created by Jeremy Rand on 2015-07-15. +// Copyright (c) 2015 Jeremy Rand. All rights reserved. +// + + +#include + +#include "game.h" +#include "puzzles.h" + + +// Macros +#define SQUARE_XY(x, y) (theGame.squares[((y) * BOARD_SIZE) + (x)]) + + +// Typedefs + +typedef struct tGameSquare { + tSquareVal value; + tScratchValues scratchValues; + bool knownAtStart; + bool correct; + bool invalid; +} tGameSquare; + + +typedef struct tGame { + tGameSquare squares[BOARD_SIZE * BOARD_SIZE]; + struct tPuzzle *puzzle; + tUpdatePosCallback callback; +} tGame; + + +// Globals + +tGame theGame; + + +// Implementation + +void refreshPos(tPos x, tPos y) +{ + tGameSquare *square; + + if (theGame.callback == NULL) + return; + + square = &(SQUARE_XY(x, y)); + theGame.callback(x, y, square->value, square->scratchValues, square->correct, square->invalid); +} + + +void startGame(tUpdatePosCallback callback) +{ + tPos x, y; + + theGame.puzzle = getRandomPuzzle(); + theGame.callback = callback; + memset(&(theGame.squares), 0, sizeof(theGame.squares)); + + for (y = 0; y < BOARD_SIZE; y++) { + for (x = 0; x < BOARD_SIZE; x++) { + tSquareVal squareVal = getStartValueAtPos(theGame.puzzle, x, y); + + if (squareVal != EMPTY_SQUARE) { + SQUARE_XY(x, y).value = squareVal; + SQUARE_XY(x, y).knownAtStart = true; + SQUARE_XY(x, y).correct = true; + } + refreshPos(x, y); + } + } +} + + +void refreshAllPos(void) +{ + tPos x, y; + + for (y = 0; y < BOARD_SIZE; y++) { + for (x = 0; x < BOARD_SIZE; x++) { + refreshPos(x, y); + } + } +} + + +bool isPuzzleSolved(void) +{ + tPos x, y; + + for (y = 0; y < BOARD_SIZE; y++) { + for (x = 0; x < BOARD_SIZE; x++) { + if (!(SQUARE_XY(x, y).correct)) + return false; + } + } + return true; +} + + +bool isSquareInvalid(tPos col, tPos row) +{ + tSquareVal value = SQUARE_XY(col, row).value; + tPos x, y; + tPos subSquareXStart, subSquareXEnd; + tPos subSquareYStart, subSquareYEnd; + + // Empty is always valid + if (value == EMPTY_SQUARE) + return false; + + for (y = 0; y < BOARD_SIZE; y++) { + // If this value appears somewhere else in the same column, it is invalid + if ((y != row) && + (value == SQUARE_XY(col, y).value)) + return true; + } + + for (x = 0; x < BOARD_SIZE; x++) { + // If this value appears somewhere else in the same row, it is invalid + if ((x != col) && + (value == SQUARE_XY(x, row).value)) + return true; + } + + // Need to find the sub-square for this position and check among them... + subSquareXStart = ((col / SUBSQUARE_SIZE) * SUBSQUARE_SIZE); + subSquareXEnd = subSquareXStart + SUBSQUARE_SIZE; + + subSquareYStart = ((row / SUBSQUARE_SIZE) * SUBSQUARE_SIZE); + subSquareYEnd = subSquareYStart + SUBSQUARE_SIZE; + for (y = subSquareYStart; y < subSquareYEnd; y++) { + for (x = subSquareXStart; x < subSquareXEnd; x++) { + if ((x != col) && + (y != row) && + (value == SQUARE_XY(x, y).value)) + return true; + } + } + + // If we haven't seen this same value in the column, row or subsquare, + // then it is not invalid (it is valid). + return false; +} + + +bool refreshInvalid(tPos col, tPos row) +{ + bool update = false; + tPos x, y; + + for (y = 0; y < BOARD_SIZE; y++) { + for (x = 0; x < BOARD_SIZE; x++) { + bool newInvalid = isSquareInvalid(x, y); + if (newInvalid != SQUARE_XY(x, y).invalid) { + SQUARE_XY(x, y).invalid = isSquareInvalid(x, y); + + if ((col == x) && + (row == y)) + update = true; + else + refreshPos(x, y); + } + } + } + + return update; +} + + +bool setValueAtPos(tPos x, tPos y, tSquareVal val) +{ + tGameSquare *square = &(SQUARE_XY(x, y)); + bool update = false; + bool correct; + + if (square->knownAtStart) { + return false; + } + + if (square->value != val) { + square->value = val; + update = true; + } + + if (square->scratchValues != 0) { + square->scratchValues = 0; + update = true; + } + + correct = checkValueAtPos(theGame.puzzle, val, x, y); + if (square->correct != correct) { + square->correct = correct; + update = true; + } + + if (refreshInvalid(x, y)) + update = true; + + if (update) + refreshPos(x, y); + + return true; +} + + +bool toggleScratchValueAtPos(tPos x, tPos y, tSquareVal val) +{ + tGameSquare *square = &(SQUARE_XY(x, y)); + + if (square->knownAtStart) { + return false; + } + square->scratchValues ^= (0x1 << val); + refreshPos(x, y); + + return true; +} \ No newline at end of file diff --git a/a2sudoku/game.h b/a2sudoku/game.h new file mode 100644 index 0000000..2ab54b0 --- /dev/null +++ b/a2sudoku/game.h @@ -0,0 +1,39 @@ +// +// game.h +// a2sudoku +// +// Created by Jeremy Rand on 2015-07-15. +// Copyright (c) 2015 Jeremy Rand. All rights reserved. +// + + +#include "puzzles.h" + +#ifndef __a2sudoku__game__ +#define __a2sudoku__game__ + + +// Typedefs + +typedef uint16_t tScratchValues; +typedef void (*tUpdatePosCallback)(tPos x, tPos y, tSquareVal val, tScratchValues scratch, bool correct, bool invalid); + + +// API + +extern void startGame(tUpdatePosCallback callback); + +extern void refreshAllPos(void); + +extern void refreshPos(tPos x, tPos y); + +extern bool isPuzzleSolved(void); + +// Returns false if unable to set the value for some reason +extern bool setValueAtPos(tPos x, tPos y, tSquareVal val); + +// Returns false if unable to toggle the scratch value for some reason +extern bool toggleScratchValueAtPos(tPos x, tPos y, tSquareVal val); + + +#endif /* defined(__a2sudoku__game__) */ diff --git a/a2sudoku/main.c b/a2sudoku/main.c index 6ee4eae..1f7b1b2 100644 --- a/a2sudoku/main.c +++ b/a2sudoku/main.c @@ -11,10 +11,16 @@ #include #include +#include "ui.h" + int main(void) { - printf("HELLO, WORLD!\n"); - cgetc(); + displayInstructions(); + + while (playGame()) { + // Loop back and play another game until playGame() returns false. + } + return 0; } diff --git a/a2sudoku/make/V2Make.scpt b/a2sudoku/make/V2Make.scpt index 7f623e571add293dbb6d675a4096a017b360293e..16a76d6f6f97f3455a4e306aaab119ebcd32581e 100644 GIT binary patch delta 325 zcmZ9EF-yZx6opUfkU(D41O#!akUCi8m4HjOVuvbr3^)lPN$DdYDS3IF)uH_XkFNd( zi+{o?li(~kIr$U3i_m(Pd+s^kJFP(tYM$EYN|$CUGLlrjoPn zc!b?))$?H7Cy$vuE!faxX3(a`zTU7w*s8Awid;qZTWfG6BJQ&ksJQDh_zwJKK)(%ZM zZX8Q-5~Lyu69;?4Oa^H*QX9qQmVq4F1P>+D{`c5l?cuWcoZGwtLkAHgG7Q0y(A|K* z06si*Y##(JVuGZsPDw_YL=P?Em^?`wf?GI)Ho@4&7^`GNND +#include + +#include "puzzles.h" + + +// Macros + +#define PUZZLE_SOLVED_VAL(square) ((square) & 0xf) +#define PUZZLE_START_VAL(square) (((square) & 0x10) ? PUZZLE_SOLVED_VAL(square) : EMPTY_SQUARE) + +#define PUZZLE_SQUARE(puzzle, x, y) ((puzzle)->squares[((y) * BOARD_SIZE) + (x)]) + +// PVAL is used to record the value of a square in a puzzle which is unknown at the start of the game. +// PVAL is short for "puzzle value" +#define PVAL(value) ((value) & 0xf) + +// SVAL is used to record the value of a square in a puzzle which is known at the start of the game. +// SVAL is short for "starting value" +#define SVAL(value) (((value) & 0xf) | 0x10) + + +// Typedefs + +typedef uint8_t tPuzzleNum; + +typedef struct tPuzzle { + tSquareVal squares[BOARD_SIZE * BOARD_SIZE]; +} tPuzzle; + + +// Forward declarations + +tPuzzle puzzles[]; + +tPuzzleNum numPuzzles(void); + + +// Implementation + +tPuzzle *getRandomPuzzle(void) +{ + tPuzzleNum randomPuzzleNum = (rand() % numPuzzles()); + return &(puzzles[randomPuzzleNum]); +} + + + +tSquareVal getStartValueAtPos(tPuzzle *puzzle, tPos x, tPos y) +{ + return PUZZLE_START_VAL(PUZZLE_SQUARE(puzzle, x, y)); +} + + +bool checkValueAtPos(tPuzzle *puzzle, tSquareVal val, tPos x, tPos y) +{ + return (PUZZLE_SOLVED_VAL(PUZZLE_SQUARE(puzzle, x, y)) == val); +} + + +void printPuzzle(tPuzzle *puzzle, bool solution) +{ + tPos x, y; + + for (y = 0; y < BOARD_SIZE; y++) { + if ((y % SUBSQUARE_SIZE) == 0) { + printf("\n"); + } + + for (x = 0; x < BOARD_SIZE; x++) { + char displayChar = ' '; + tSquareVal squareVal; + + if ((x % SUBSQUARE_SIZE) == 0) { + printf(" "); + } + if (solution) { + squareVal = PUZZLE_SOLVED_VAL(PUZZLE_SQUARE(puzzle, x, y)); + } else { + squareVal = PUZZLE_START_VAL(PUZZLE_SQUARE(puzzle, x, y)); + } + + if (squareVal != EMPTY_SQUARE) + displayChar = '0' + squareVal; + + printf(" %c ", displayChar); + } + printf("\n"); + } +} + + +// Puzzle definitions + +tPuzzle puzzles[] = { + { + { + PVAL(4),PVAL(3),PVAL(5), SVAL(2),SVAL(6),PVAL(9), SVAL(7),PVAL(8),SVAL(1), + SVAL(6),SVAL(8),PVAL(2), PVAL(5),SVAL(7),PVAL(1), PVAL(4),SVAL(9),PVAL(3), + SVAL(1),SVAL(9),PVAL(7), PVAL(8),PVAL(3),SVAL(4), SVAL(5),PVAL(6),PVAL(2), + + SVAL(8),SVAL(2),PVAL(6), SVAL(1),PVAL(9),PVAL(5), PVAL(3),SVAL(4),PVAL(7), + PVAL(3),PVAL(7),SVAL(4), SVAL(6),PVAL(8),SVAL(2), SVAL(9),PVAL(1),PVAL(5), + PVAL(9),SVAL(5),PVAL(1), PVAL(7),PVAL(4),SVAL(3), PVAL(6),SVAL(2),SVAL(8), + + PVAL(5),PVAL(1),SVAL(9), SVAL(3),PVAL(2),PVAL(6), PVAL(8),SVAL(7),SVAL(4), + PVAL(2),SVAL(4),PVAL(8), PVAL(9),SVAL(5),PVAL(7), PVAL(1),SVAL(3),SVAL(6), + SVAL(7),PVAL(6),SVAL(3), PVAL(4),SVAL(1),SVAL(8), PVAL(2),PVAL(5),PVAL(9) + } + }, +}; + + +tPuzzleNum numPuzzles(void) +{ + return sizeof(puzzles) / sizeof(puzzles[0]); +} \ No newline at end of file diff --git a/a2sudoku/puzzles.h b/a2sudoku/puzzles.h new file mode 100644 index 0000000..47359e9 --- /dev/null +++ b/a2sudoku/puzzles.h @@ -0,0 +1,51 @@ +// +// puzzles.h +// a2sudoku +// +// Created by Jeremy Rand on 2015-07-15. +// Copyright (c) 2015 Jeremy Rand. All rights reserved. +// + + +#include +#include + + +#ifndef __a2sudoku__puzzles__ +#define __a2sudoku__puzzles__ + + +// Defines + +// A subsquare is the 3x3 square inside which each number appears once +#define SUBSQUARE_SIZE 3 + +// The board has dimensions of the square of the subsquare size +#define BOARD_SIZE (SUBSQUARE_SIZE * SUBSQUARE_SIZE) + +#define EMPTY_SQUARE 0 + + +// Forward declarations + +struct tPuzzle; + + +// Typedefs + +typedef uint8_t tSquareVal; +typedef uint8_t tPos; + + +// API + +extern struct tPuzzle *getRandomPuzzle(void); + +extern tSquareVal getStartValueAtPos(struct tPuzzle *puzzle, tPos x, tPos y); + +extern bool checkValueAtPos(struct tPuzzle *puzzle, tSquareVal val, tPos x, tPos y); + +extern void printPuzzle(struct tPuzzle *puzzle, bool solution); + + +#endif /* defined(__a2sudoku__puzzles__) */ diff --git a/a2sudoku/ui.c b/a2sudoku/ui.c new file mode 100644 index 0000000..1b80b71 --- /dev/null +++ b/a2sudoku/ui.c @@ -0,0 +1,270 @@ +// +// ui.c +// a2sudoku +// +// Created by Jeremy Rand on 2015-07-15. +// Copyright (c) 2015 Jeremy Rand. All rights reserved. +// + + +#include +#include +#include +#include +#include + +#include "game.h" +#include "ui.h" + + +// Extern symbols for graphics drivers +extern char a2e_hi; + + +// Macros and defines +#define SQUARE_WIDTH 29 +#define SQUARE_HEIGHT 19 + +#define THICK_LINE_WIDTH 2 +#define THIN_LINE_WIDTH 1 +#define THICK_LINE_HEIGHT 2 +#define THIN_LINE_HEIGHT 1 + +#define TEXT_OFFSET_X 12 +#define TEXT_OFFSET_Y 6 + +#define TOTAL_WIDTH ((BOARD_SIZE * SQUARE_WIDTH) + \ + ((BOARD_SIZE + 1) * THIN_LINE_WIDTH) + \ + (((BOARD_SIZE / SUBSQUARE_SIZE) + 1) * (THICK_LINE_WIDTH - THIN_LINE_WIDTH))) + +#define TOTAL_HEIGHT ((BOARD_SIZE * SQUARE_HEIGHT) + \ + ((BOARD_SIZE + 1) * THIN_LINE_HEIGHT) + \ + (((BOARD_SIZE / SUBSQUARE_SIZE) + 1) * (THICK_LINE_HEIGHT - THIN_LINE_HEIGHT))) + + +// Globals; + +tPos cursorX, cursorY; +int screenSquaresX[BOARD_SIZE]; +int screenSquaresY[BOARD_SIZE]; + + +// Implementation + + +void initUI(void) +{ + static bool tgi_inited = false; + tPos pos; + int xPos = 0; + int yPos = 0; + + if (tgi_inited) + return; + + // Install drivers + tgi_install(&a2e_hi); + + tgi_init(); + tgi_clear(); + + tgi_setcolor(COLOR_WHITE); + for (pos = 0; pos <= BOARD_SIZE; pos++) { + if ((pos % SUBSQUARE_SIZE) == 0) { + tgi_bar(xPos, 0, xPos + THICK_LINE_WIDTH - 1, TOTAL_HEIGHT - 1); + xPos += THICK_LINE_WIDTH; + + tgi_bar(0, yPos, TOTAL_WIDTH - 1, yPos + THICK_LINE_HEIGHT - 1); + yPos += THICK_LINE_HEIGHT; + } else { + tgi_bar(xPos, 0, xPos + THIN_LINE_WIDTH - 1, TOTAL_HEIGHT - 1); + xPos += THIN_LINE_WIDTH; + + tgi_bar(0, yPos, TOTAL_WIDTH - 1, yPos + THIN_LINE_HEIGHT - 1); + yPos += THIN_LINE_HEIGHT; + } + + if (pos < BOARD_SIZE) { + screenSquaresX[pos] = xPos; + screenSquaresY[pos] = yPos; + } + + xPos += SQUARE_WIDTH; + yPos += SQUARE_HEIGHT; + } + + tgi_inited = true; +} + + +void shutdownUI(void) +{ + // Uninstall drivers + tgi_uninstall(); +} + + +void displayInstructions(void) +{ + int seed = 0; + + clrscr(); + + // 1111111111222222222233333333334 + // 1234567890123456789012345678901234567890 + printf( + " Apple ][ Sudoku\n" + " By Jeremy Rand\n" + "\n" + "The goal is to get the numbers from 1 to" + "9 uniquely in each column, row and 3x3\n" + "subsquare. Move the cursor with I-J-K-L" + "or the arrow keys. Press a number key\n" + "to enter a value. Press a number key\n" + "while holding shift or closed apple to\n" + "toggle a scratch value. Press 0 to\n" + "clear a square.\n" + "\n" + "Play ends when the puzzle is solved.\n" + "\n" + "Press escape or Q to quit at any time.\n" + "Press R to start a new game.\n" + "Press H to see this info again.\n" + "\n" + "\n" + "\n" + " Press any key to start"); + + // The amount of time the user waits to read the in + while (!kbhit()) + seed++; + + cgetc(); + srand(seed); + + clrscr(); +} + + +void updatePos(tPos x, tPos y, tSquareVal val, tScratchValues scratch, bool correct, bool invalid) +{ + int screenX = screenSquaresX[x]; + int screenY = screenSquaresY[y]; + int edgeX = screenX + SQUARE_WIDTH - 1; + int edgeY = screenY + SQUARE_HEIGHT - 1; + char buffer[2]; + + tgi_setcolor(COLOR_BLACK); + tgi_bar(screenX, screenY, edgeX, edgeY); + + tgi_setcolor(COLOR_WHITE); + if (val != EMPTY_SQUARE) { + buffer[0] = '0' + val; + buffer[1] = '\0'; + + tgi_outtextxy(screenX + TEXT_OFFSET_X, screenY + TEXT_OFFSET_Y, buffer); + + if (!correct) + tgi_line(screenX, edgeY, edgeX, screenY); + + if (invalid) + tgi_line(screenX, edgeY, edgeX, screenY); + } + + if ((cursorX == x) && + (cursorY == y)) { + tgi_line(screenX, screenY, edgeX, screenY); + tgi_lineto(edgeX, edgeY); + tgi_lineto(screenX, edgeY); + tgi_lineto(screenX, screenY); + } +} + + +bool playGame(void) +{ + initUI(); + + cursorX = 0; + cursorY = 0; + + startGame(updatePos); + + while (true) { + char ch = cgetc(); + + switch (ch) { + case 'h': + case 'H': + displayInstructions(); + clrscr(); + refreshAllPos(); + break; + + case 'r': + case 'R': + return true; + + case 'q': + case 'Q': + case CH_ESC: + shutdownUI(); + return false; + + case 'i': + case 'I': + case CH_CURS_UP: + if (cursorY != 0) { + cursorY--; + refreshPos(cursorX, cursorY); + refreshPos(cursorX, cursorY + 1); + } + break; + + case 'j': + case 'J': + case CH_CURS_LEFT: + if (cursorX != 0) { + cursorX--; + refreshPos(cursorX, cursorY); + refreshPos(cursorX + 1, cursorY); + } + break; + + case 'k': + case 'K': + case CH_CURS_RIGHT: + if (cursorX < BOARD_SIZE - 1) { + cursorX++; + refreshPos(cursorX, cursorY); + refreshPos(cursorX - 1, cursorY); + } + break; + + case 'm': + case 'M': + case CH_CURS_DOWN: + if (cursorY < BOARD_SIZE - 1) { + cursorY++; + refreshPos(cursorX, cursorY); + refreshPos(cursorX, cursorY - 1); + } + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + setValueAtPos(cursorX, cursorY, ch - '0'); + break; + } + } + + return false; +} \ No newline at end of file diff --git a/a2sudoku/ui.h b/a2sudoku/ui.h new file mode 100644 index 0000000..925f3e8 --- /dev/null +++ b/a2sudoku/ui.h @@ -0,0 +1,23 @@ +// +// ui.h +// a2sudoku +// +// Created by Jeremy Rand on 2015-07-15. +// Copyright (c) 2015 Jeremy Rand. All rights reserved. +// + + +#include + +#ifndef __a2sudoku__ui__ +#define __a2sudoku__ui__ + + +// API + +extern void displayInstructions(void); + +extern bool playGame(void); + + +#endif /* defined(__a2sudoku__ui__) */